New upstream version 2.9.0+dfsg1

This commit is contained in:
Mike Gabriel 2022-11-28 09:30:00 +01:00
parent 03a18ec27e
commit 97496cbb22
39 changed files with 1630 additions and 253 deletions

View File

@ -85,7 +85,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(RAW_VERSION_STRING "2.8.1")
set(RAW_VERSION_STRING "2.9.0")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)

View File

@ -1,3 +1,29 @@
# 2022-11-16 Version 2.9.0
Notewhorth changes:
* Backported #8252: Support sending server redirection PDU
* Backported #8406: Ensure X11 client cursor is never smaller 1x1
* Backported #8403: Fixed multiple client side input validation issues
(CVE-2022-39316, CVE-2022-39317, CVE-2022-39318, CVE-2022-39319,
CVE-2022-39320, CVE-2022-41877, CVE-2022-39347)
* Backported #7282: Proxy server now discards input events sent before
activation was received
* Backported #8324: Internal replacements for md4, md5 and hmac-md5
For the time being the RDP protocol requires these outdated hash
algorithms. So any distribution that wants to ship a working
FreeRDP should check the options WITH_INTERNAL_MD4 (and depending
on OpenSSL deprecation status WITH_INTERNAL_MD5)
Fixed issues:
* Backported #8341: Null checks in winpr_Digest_Free
* Backported #8335: Missing NULL return in winpr_Digest_New
* Backported #8192: Support for audin version 2 microphone channel
* Backported #7282: Discard input events before activation (Fixes #8374)
For a complete and detailed change log since the last release run:
git log 2.8.1..2.9.0
# 2022-10-12 Version 2.8.1
Notewhorth changes:

View File

@ -43,13 +43,18 @@
#include "audin_main.h"
#define MSG_SNDIN_VERSION 0x01
#define MSG_SNDIN_FORMATS 0x02
#define MSG_SNDIN_OPEN 0x03
#define MSG_SNDIN_OPEN_REPLY 0x04
#define MSG_SNDIN_DATA_INCOMING 0x05
#define MSG_SNDIN_DATA 0x06
#define MSG_SNDIN_FORMATCHANGE 0x07
#define SNDIN_VERSION 0x02
enum
{
MSG_SNDIN_VERSION = 0x01,
MSG_SNDIN_FORMATS = 0x02,
MSG_SNDIN_OPEN = 0x03,
MSG_SNDIN_OPEN_REPLY = 0x04,
MSG_SNDIN_DATA_INCOMING = 0x05,
MSG_SNDIN_DATA = 0x06,
MSG_SNDIN_FORMATCHANGE = 0x07
} MSG_SNDIN_CMD;
typedef struct _AUDIN_LISTENER_CALLBACK AUDIN_LISTENER_CALLBACK;
struct _AUDIN_LISTENER_CALLBACK
@ -105,6 +110,7 @@ struct _AUDIN_PLUGIN
IWTSListener* listener;
BOOL initialized;
UINT32 version;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
@ -138,7 +144,7 @@ static UINT audin_channel_write_and_free(AUDIN_CHANNEL_CALLBACK* callback, wStre
static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
{
wStream* out;
const UINT32 ClientVersion = 0x01;
const UINT32 ClientVersion = SNDIN_VERSION;
UINT32 ServerVersion;
if (Stream_GetRemainingLength(s) < 4)
@ -149,7 +155,7 @@ static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
ServerVersion, ClientVersion);
/* Do not answer server packet, we do not support the channel version. */
if (ServerVersion != ClientVersion)
if (ServerVersion > ClientVersion)
{
WLog_Print(audin->log, WLOG_WARN,
"Incompatible channel version server=%" PRIu32
@ -157,6 +163,7 @@ static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c
ServerVersion, ClientVersion);
return CHANNEL_RC_OK;
}
audin->version = ServerVersion;
out = Stream_New(NULL, 5);

View File

@ -61,10 +61,14 @@
} while (0)
#endif
static void drive_file_fix_path(WCHAR* path)
static BOOL drive_file_fix_path(WCHAR* path, size_t length)
{
size_t i;
size_t length = _wcslen(path);
if ((length == 0) || (length > UINT32_MAX))
return FALSE;
WINPR_ASSERT(path);
for (i = 0; i < length; i++)
{
@ -75,58 +79,82 @@ static void drive_file_fix_path(WCHAR* path)
#ifdef WIN32
if ((length == 3) && (path[1] == L':') && (path[2] == L'/'))
return;
return FALSE;
#else
if ((length == 1) && (path[0] == L'/'))
return;
return FALSE;
#endif
if ((length > 0) && (path[length - 1] == L'/'))
path[length - 1] = L'\0';
return TRUE;
}
static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
size_t PathLength)
size_t PathWCharLength)
{
WCHAR* fullpath;
size_t base_path_length;
BOOL ok = FALSE;
WCHAR* fullpath = NULL;
size_t length;
if (!base_path || (!path && (PathLength > 0)))
return NULL;
if (!base_path || (!path && (PathWCharLength > 0)))
goto fail;
base_path_length = _wcslen(base_path) * 2;
fullpath = (WCHAR*)calloc(1, base_path_length + PathLength + sizeof(WCHAR));
const size_t base_path_length = _wcsnlen(base_path, MAX_PATH);
length = base_path_length + PathWCharLength + 1;
fullpath = (WCHAR*)calloc(length, sizeof(WCHAR));
if (!fullpath)
goto fail;
CopyMemory(fullpath, base_path, base_path_length * sizeof(WCHAR));
if (path)
CopyMemory(&fullpath[base_path_length], path, PathWCharLength * sizeof(WCHAR));
if (!drive_file_fix_path(fullpath, length))
goto fail;
/* Ensure the path does not contain sequences like '..' */
const WCHAR dotdot[] = { '.', '.', '\0' };
if (_wcsstr(&fullpath[base_path_length], dotdot))
{
WLog_ERR(TAG, "malloc failed!");
return NULL;
char abuffer[MAX_PATH] = { 0 };
ConvertFromUnicode(CP_UTF8, 0, &fullpath[base_path_length], -1, (char**)&abuffer,
ARRAYSIZE(abuffer) - 1, NULL, NULL);
WLog_WARN(TAG, "[rdpdr] received invalid file path '%s' from server, aborting!",
&abuffer[base_path_length]);
goto fail;
}
CopyMemory(fullpath, base_path, base_path_length);
if (path)
CopyMemory((char*)fullpath + base_path_length, path, PathLength);
drive_file_fix_path(fullpath);
ok = TRUE;
fail:
if (!ok)
{
free(fullpath);
fullpath = NULL;
}
return fullpath;
}
static BOOL drive_file_remove_dir(const WCHAR* path)
{
WIN32_FIND_DATAW findFileData;
WIN32_FIND_DATAW findFileData = { 0 };
BOOL ret = TRUE;
HANDLE dir;
WCHAR* fullpath;
WCHAR* path_slash;
size_t base_path_length;
HANDLE dir = INVALID_HANDLE_VALUE;
WCHAR* fullpath = NULL;
WCHAR* path_slash = NULL;
size_t base_path_length = 0;
if (!path)
return FALSE;
base_path_length = _wcslen(path) * 2;
path_slash = (WCHAR*)calloc(1, base_path_length + sizeof(WCHAR) * 3);
base_path_length = _wcslen(path);
path_slash = (WCHAR*)calloc(base_path_length + 3, sizeof(WCHAR));
if (!path_slash)
{
@ -134,12 +162,11 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
return FALSE;
}
CopyMemory(path_slash, path, base_path_length);
path_slash[base_path_length / 2] = L'/';
path_slash[base_path_length / 2 + 1] = L'*';
CopyMemory(path_slash, path, base_path_length * sizeof(WCHAR));
path_slash[base_path_length] = L'/';
path_slash[base_path_length + 1] = L'*';
DEBUG_WSTR("Search in %s", path_slash);
dir = FindFirstFileW(path_slash, &findFileData);
path_slash[base_path_length / 2 + 1] = 0;
if (dir == INVALID_HANDLE_VALUE)
{
@ -149,7 +176,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
do
{
size_t len = _wcslen(findFileData.cFileName);
const size_t len = _wcsnlen(findFileData.cFileName, ARRAYSIZE(findFileData.cFileName));
if ((len == 1 && findFileData.cFileName[0] == L'.') ||
(len == 2 && findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.'))
@ -157,7 +184,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
continue;
}
fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len * 2);
fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len);
DEBUG_WSTR("Delete %s", fullpath);
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
@ -333,13 +360,13 @@ static BOOL drive_file_init(DRIVE_FILE* file)
return file->file_handle != INVALID_HANDLE_VALUE;
}
DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions,
UINT32 FileAttributes, UINT32 SharedAccess)
DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
{
DRIVE_FILE* file;
if (!base_path || (!path && (PathLength > 0)))
if (!base_path || (!path && (PathWCharLength > 0)))
return NULL;
file = (DRIVE_FILE*)calloc(1, sizeof(DRIVE_FILE));
@ -359,7 +386,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat
file->CreateDisposition = CreateDisposition;
file->CreateOptions = CreateOptions;
file->SharedAccess = SharedAccess;
drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathLength));
drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathWCharLength));
if (!drive_file_init(file))
{
@ -714,13 +741,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
return FALSE;
fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input),
FileNameLength);
FileNameLength / sizeof(WCHAR));
if (!fullpath)
{
WLog_ERR(TAG, "drive_file_combine_fullpath failed!");
return FALSE;
}
#ifdef _WIN32
@ -759,7 +783,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
}
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
const WCHAR* path, UINT32 PathLength, wStream* output)
const WCHAR* path, UINT32 PathWCharLength, wStream* output)
{
size_t length;
WCHAR* ent_path;
@ -773,7 +797,7 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
if (file->find_handle != INVALID_HANDLE_VALUE)
FindClose(file->find_handle);
ent_path = drive_file_combine_fullpath(file->basepath, path, PathLength);
ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength);
/* open new search handle and retrieve the first entry */
file->find_handle = FindFirstFileW(ent_path, &file->find_data);
free(ent_path);

View File

@ -51,9 +51,9 @@ struct _DRIVE_FILE
UINT32 CreateOptions;
};
DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions,
UINT32 FileAttributes, UINT32 SharedAccess);
DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess);
BOOL drive_file_free(DRIVE_FILE* file);
BOOL drive_file_open(DRIVE_FILE* file);
@ -64,6 +64,6 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
wStream* input);
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
const WCHAR* path, UINT32 PathLength, wStream* output);
const WCHAR* path, UINT32 PathWCharLength, wStream* output);
#endif /* FREERDP_CHANNEL_DRIVE_FILE_H */

View File

@ -184,8 +184,8 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
path = (const WCHAR*)Stream_Pointer(irp->input);
FileId = irp->devman->id_sequence++;
file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition,
CreateOptions, FileAttributes, SharedAccess);
file = drive_file_new(drive->path, path, PathLength / sizeof(WCHAR), FileId, DesiredAccess,
CreateDisposition, CreateOptions, FileAttributes, SharedAccess);
if (!file)
{
@ -629,6 +629,9 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
Stream_Read_UINT32(irp->input, PathLength);
Stream_Seek(irp->input, 23); /* Padding */
path = (WCHAR*)Stream_Pointer(irp->input);
if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, PathLength))
return ERROR_INVALID_DATA;
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
@ -636,8 +639,8 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
irp->IoStatus = STATUS_UNSUCCESSFUL;
Stream_Write_UINT32(irp->output, 0); /* Length */
}
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, PathLength,
irp->output))
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path,
PathLength / sizeof(WCHAR), irp->output))
{
irp->IoStatus = drive_map_windows_err(GetLastError());
}

View File

@ -97,7 +97,13 @@ static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId,
UINT32 OutputBufferSize)
{
const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
wStream* out = Stream_New(NULL, OutputBufferSize + 28);
#if UINT32_MAX >= SIZE_MAX
if (OutputBufferSize > UINT32_MAX - 28ull)
return NULL;
#endif
wStream* out = Stream_New(NULL, OutputBufferSize + 28ull);
if (!out)
return NULL;
@ -241,6 +247,10 @@ static UINT urbdrc_process_io_control(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* c
Stream_Read_UINT32(s, OutputBufferSize);
Stream_Read_UINT32(s, RequestId);
if (OutputBufferSize > UINT32_MAX - 4)
return ERROR_INVALID_DATA;
InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
@ -673,7 +683,11 @@ static UINT urb_control_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callba
buffer = Stream_Pointer(out);
if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
return ERROR_INVALID_DATA;
Stream_Copy(s, out, OutputBufferSize);
}
/** process TS_URB_CONTROL_TRANSFER */
if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
@ -720,6 +734,15 @@ static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBA
Stream_Read_UINT32(s, TransferFlags); /** TransferFlags */
Stream_Read_UINT32(s, OutputBufferSize);
EndpointAddress = (PipeHandle & 0x000000ff);
if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
{
return ERROR_INVALID_DATA;
}
}
/** process TS_URB_BULK_OR_INTERRUPT_TRANSFER */
return pdev->bulk_or_interrupt_transfer(
pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
@ -804,6 +827,13 @@ static UINT urb_isoch_transfer(IUDEVICE* pdev, URBDRC_CHANNEL_CALLBACK* callback
packetDescriptorData = Stream_Pointer(s);
Stream_Seek(s, NumberOfPackets * 12);
Stream_Read_UINT32(s, OutputBufferSize);
if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
return ERROR_INVALID_DATA;
}
return pdev->isoch_transfer(
pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,

View File

@ -1221,12 +1221,18 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
if (!Buffer)
Stream_Seek(user_data->data, (NumberOfPackets * 12));
iso_packet_size = BufferSize / NumberOfPackets;
iso_transfer = libusb_alloc_transfer(NumberOfPackets);
if (NumberOfPackets > 0)
{
iso_packet_size = BufferSize / NumberOfPackets;
iso_transfer = libusb_alloc_transfer((int)NumberOfPackets);
}
if (iso_transfer == NULL)
{
WLog_Print(urbdrc->log, WLOG_ERROR, "Error: libusb_alloc_transfer.");
WLog_Print(urbdrc->log, WLOG_ERROR,
"Error: libusb_alloc_transfer [NumberOfPackets=%" PRIu32 ", BufferSize=%" PRIu32
" ]",
NumberOfPackets, BufferSize);
async_transfer_user_data_free(user_data);
return -1;
}

View File

@ -258,8 +258,8 @@ static BOOL xf_Pointer_GetCursorForCurrentScale(rdpContext* context, const rdpPo
xscale = (settings->SmartSizing ? xfc->scaledWidth / (double)settings->DesktopWidth : 1);
yscale = (settings->SmartSizing ? xfc->scaledHeight / (double)settings->DesktopHeight : 1);
xTargetSize = pointer->width * xscale;
yTargetSize = pointer->height * yscale;
xTargetSize = MAX(1, pointer->width * xscale);
yTargetSize = MAX(1, pointer->height * yscale);
WLog_DBG(TAG, "%s: scaled: %" PRIu32 "x%" PRIu32 ", desktop: %" PRIu32 "x%" PRIu32, __func__,
xfc->scaledWidth, xfc->savedHeight, settings->DesktopWidth, settings->DesktopHeight);

View File

@ -183,4 +183,7 @@
/* Proxy */
#cmakedefine WITH_PROXY_MODULES
#cmakedefine WITH_INTERNAL_MD4
#cmakedefine WITH_INTERNAL_MD5
#endif /* FREERDP_CONFIG_H */

View File

@ -70,6 +70,25 @@ extern "C"
#define VERIFY_CERT_FLAG_MISMATCH 0x80
#define VERIFY_CERT_FLAG_MATCH_LEGACY_SHA1 0x100
typedef enum
{
CONNECTION_STATE_INITIAL,
CONNECTION_STATE_NEGO,
CONNECTION_STATE_NLA,
CONNECTION_STATE_MCS_CONNECT,
CONNECTION_STATE_MCS_ERECT_DOMAIN,
CONNECTION_STATE_MCS_ATTACH_USER,
CONNECTION_STATE_MCS_CHANNEL_JOIN,
CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT,
CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE,
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT,
CONNECTION_STATE_LICENSING,
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING,
CONNECTION_STATE_CAPABILITIES_EXCHANGE,
CONNECTION_STATE_FINALIZATION,
CONNECTION_STATE_ACTIVE
} CONNECTION_STATE;
/* Message types used by gateway messaging callback */
#define GATEWAY_MESSAGE_CONSENT 1
#define GATEWAY_MESSAGE_SERVICE 2
@ -527,6 +546,9 @@ extern "C"
FREERDP_API const char* freerdp_nego_get_routing_token(rdpContext* context, DWORD* length);
FREERDP_API CONNECTION_STATE freerdp_get_state(rdpContext* context);
FREERDP_API const char* freerdp_state_string(CONNECTION_STATE state);
#ifdef __cplusplus
}
#endif

View File

@ -48,6 +48,13 @@ typedef BOOL (*psPeerCapabilities)(freerdp_peer* peer);
typedef BOOL (*psPeerPostConnect)(freerdp_peer* peer);
typedef BOOL (*psPeerActivate)(freerdp_peer* peer);
typedef BOOL (*psPeerLogon)(freerdp_peer* peer, SEC_WINNT_AUTH_IDENTITY* identity, BOOL automatic);
typedef BOOL (*psPeerSendServerRedirection)(freerdp_peer* peer, UINT32 sessionId,
const char* targetNetAddress, const char* routingToken,
const char* userName, const char* domain,
const char* password, const char* targetFQDN,
const char* targetNetBiosName, DWORD tsvUrlLength,
const BYTE* tsvUrl, UINT32 targetNetAddressesCount,
const char** targetNetAddresses);
typedef BOOL (*psPeerAdjustMonitorsLayout)(freerdp_peer* peer);
typedef BOOL (*psPeerClientCapabilities)(freerdp_peer* peer);
@ -133,6 +140,8 @@ struct rdp_freerdp_peer
psPeerClientCapabilities ClientCapabilities;
psPeerComputeNtlmHash ComputeNtlmHash;
psPeerLicenseCallback LicenseCallback;
psPeerSendServerRedirection SendServerRedirection;
};
#ifdef __cplusplus

View File

@ -230,19 +230,19 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
BYTE* pbSegment;
size_t cbSegment;
if (!zgfx || !stream)
if (!zgfx || !stream || (segmentSize < 2))
return FALSE;
cbSegment = segmentSize - 1;
if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize < 1) ||
(segmentSize > UINT32_MAX))
if ((Stream_GetRemainingLength(stream) < segmentSize) || (segmentSize > UINT32_MAX))
return FALSE;
Stream_Read_UINT8(stream, flags); /* header (1 byte) */
zgfx->OutputCount = 0;
pbSegment = Stream_Pointer(stream);
Stream_Seek(stream, cbSegment);
if (!Stream_SafeSeek(stream, cbSegment))
return FALSE;
if (!(flags & PACKET_COMPRESSED))
{
@ -346,6 +346,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
if (count > zgfx->cBitsRemaining / 8)
return FALSE;
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
count);
zgfx_history_buffer_ring_write(zgfx, zgfx->pbInputCurrent, count);

View File

@ -350,7 +350,7 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
UINT16 lengthSourceDescriptor;
UINT32 timeout;
if (rdp->state == CONNECTION_STATE_ACTIVE)
if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
rdp->deactivation_reactivation = TRUE;
else
rdp->deactivation_reactivation = FALSE;
@ -390,7 +390,7 @@ BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
if (freerdp_shall_disconnect(rdp->instance))
return TRUE;
if (rdp->state == CONNECTION_STATE_ACTIVE)
if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
return TRUE;
Sleep(100);

View File

@ -2780,7 +2780,7 @@ static BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, rdpSettings* setti
Stream_Read_UINT32(&sub, captureFlags); /* captureFlags (4 bytes) */
Stream_Read_UINT32(&sub, rfxCapsLength); /* capsLength (4 bytes) */
settings->RemoteFxCaptureFlags = captureFlags;
settings->RemoteFxOnly = (captureFlags & CARDP_CAPS_CAPTURE_NON_CAC) ? TRUE : FALSE;
settings->RemoteFxOnly = (captureFlags & CARDP_CAPS_CAPTURE_NON_CAC) ? FALSE : TRUE;
if (rfxCapsLength)
{

View File

@ -188,6 +188,7 @@
static int rdp_client_connect_finalize(rdpRdp* rdp);
static BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp);
static BOOL rdp_set_state(rdpRdp* rdp, CONNECTION_STATE state);
static BOOL rdp_client_reset_codecs(rdpContext* context)
{
@ -358,7 +359,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
rdp->transport->ReceiveExtra = rdp;
transport_set_blocking_mode(rdp->transport, FALSE);
if (rdp->state != CONNECTION_STATE_NLA)
if (rdp_get_state(rdp) != CONNECTION_STATE_NLA)
{
if (!mcs_client_begin(rdp->mcs))
return FALSE;
@ -372,7 +373,7 @@ BOOL rdp_client_connect(rdpRdp* rdp)
return FALSE;
}
if (rdp->state == CONNECTION_STATE_ACTIVE)
if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
return TRUE;
Sleep(100);
@ -1137,68 +1138,69 @@ int rdp_client_transition_to_state(rdpRdp* rdp, int state)
{
int status = 0;
WLog_DBG(TAG, "%s %s --> %s", __FUNCTION__, rdp_get_state_string(rdp), rdp_state_string(state));
switch (state)
{
case CONNECTION_STATE_INITIAL:
rdp->state = CONNECTION_STATE_INITIAL;
rdp_set_state(rdp, CONNECTION_STATE_INITIAL);
break;
case CONNECTION_STATE_NEGO:
rdp->state = CONNECTION_STATE_NEGO;
rdp_set_state(rdp, CONNECTION_STATE_NEGO);
break;
case CONNECTION_STATE_NLA:
rdp->state = CONNECTION_STATE_NLA;
rdp_set_state(rdp, CONNECTION_STATE_NLA);
break;
case CONNECTION_STATE_MCS_CONNECT:
rdp->state = CONNECTION_STATE_MCS_CONNECT;
rdp_set_state(rdp, CONNECTION_STATE_MCS_CONNECT);
break;
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
rdp->state = CONNECTION_STATE_MCS_ERECT_DOMAIN;
rdp_set_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN);
break;
case CONNECTION_STATE_MCS_ATTACH_USER:
rdp->state = CONNECTION_STATE_MCS_ATTACH_USER;
rdp_set_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
break;
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
rdp->state = CONNECTION_STATE_MCS_CHANNEL_JOIN;
rdp_set_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
break;
case CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT:
rdp->state = CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT;
rdp_set_state(rdp, CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT);
break;
case CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE:
rdp->state = CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE;
rdp_set_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
break;
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT:
rdp->state = CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT;
rdp_set_state(rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT);
break;
case CONNECTION_STATE_LICENSING:
rdp->state = CONNECTION_STATE_LICENSING;
rdp_set_state(rdp, CONNECTION_STATE_LICENSING);
break;
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING:
rdp->state = CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING;
rdp_set_state(rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING);
break;
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
rdp->state = CONNECTION_STATE_CAPABILITIES_EXCHANGE;
rdp_set_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
break;
case CONNECTION_STATE_FINALIZATION:
rdp->state = CONNECTION_STATE_FINALIZATION;
rdp_set_state(rdp, CONNECTION_STATE_FINALIZATION);
update_reset_state(rdp->update);
rdp->finalize_sc_pdus = 0;
break;
case CONNECTION_STATE_ACTIVE:
rdp->state = CONNECTION_STATE_ACTIVE;
rdp_set_state(rdp, CONNECTION_STATE_ACTIVE);
{
ActivatedEventArgs activatedEvent;
rdpContext* context = rdp->context;
@ -1218,8 +1220,8 @@ int rdp_client_transition_to_state(rdpRdp* rdp, int state)
ConnectionStateChangeEventArgs stateEvent;
rdpContext* context = rdp->context;
EventArgsInit(&stateEvent, "libfreerdp");
stateEvent.state = rdp->state;
stateEvent.active = rdp->state == CONNECTION_STATE_ACTIVE;
stateEvent.state = rdp_get_state(rdp);
stateEvent.active = rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE;
PubSub_OnConnectionStateChange(context->pubSub, context, &stateEvent);
}
@ -1406,7 +1408,7 @@ BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s, UINT16 pduLength)
{
freerdp_peer* peer = rdp->context->peer;
if (rdp->state != CONNECTION_STATE_CAPABILITIES_EXCHANGE)
if (rdp_get_state(rdp) != CONNECTION_STATE_CAPABILITIES_EXCHANGE)
return FALSE;
if (!rdp_recv_confirm_active(rdp, s, pduLength))
@ -1455,74 +1457,76 @@ int rdp_server_transition_to_state(rdpRdp* rdp, int state)
{
int status = 0;
freerdp_peer* client = NULL;
const int cstate = rdp_get_state(rdp);
if (rdp->state >= CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT)
if (cstate >= CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT)
client = rdp->context->peer;
if (rdp->state < CONNECTION_STATE_ACTIVE)
if (cstate < CONNECTION_STATE_ACTIVE)
{
if (client)
client->activated = FALSE;
}
WLog_DBG(TAG, "%s %s --> %s", __FUNCTION__, rdp_get_state_string(rdp), rdp_state_string(state));
switch (state)
{
case CONNECTION_STATE_INITIAL:
rdp->state = CONNECTION_STATE_INITIAL;
rdp_set_state(rdp, CONNECTION_STATE_INITIAL);
break;
case CONNECTION_STATE_NEGO:
rdp->state = CONNECTION_STATE_NEGO;
rdp_set_state(rdp, CONNECTION_STATE_NEGO);
break;
case CONNECTION_STATE_MCS_CONNECT:
rdp->state = CONNECTION_STATE_MCS_CONNECT;
rdp_set_state(rdp, CONNECTION_STATE_MCS_CONNECT);
break;
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
rdp->state = CONNECTION_STATE_MCS_ERECT_DOMAIN;
rdp_set_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN);
break;
case CONNECTION_STATE_MCS_ATTACH_USER:
rdp->state = CONNECTION_STATE_MCS_ATTACH_USER;
rdp_set_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER);
break;
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
rdp->state = CONNECTION_STATE_MCS_CHANNEL_JOIN;
rdp_set_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN);
break;
case CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT:
rdp->state = CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT;
rdp_set_state(rdp, CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT);
break;
case CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE:
rdp->state = CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE;
rdp_set_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
break;
case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT:
rdp->state = CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT;
rdp_set_state(rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT);
break;
case CONNECTION_STATE_LICENSING:
rdp->state = CONNECTION_STATE_LICENSING;
rdp_set_state(rdp, CONNECTION_STATE_LICENSING);
break;
case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING:
rdp->state = CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING;
rdp_set_state(rdp, CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING);
break;
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
rdp->state = CONNECTION_STATE_CAPABILITIES_EXCHANGE;
rdp_set_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
rdp->AwaitCapabilities = FALSE;
break;
case CONNECTION_STATE_FINALIZATION:
rdp->state = CONNECTION_STATE_FINALIZATION;
rdp_set_state(rdp, CONNECTION_STATE_FINALIZATION);
rdp->finalize_sc_pdus = 0;
break;
case CONNECTION_STATE_ACTIVE:
rdp->state = CONNECTION_STATE_ACTIVE;
rdp_set_state(rdp, CONNECTION_STATE_ACTIVE);
update_reset_state(rdp->update);
if (client)
@ -1539,7 +1543,7 @@ int rdp_server_transition_to_state(rdpRdp* rdp, int state)
return -1;
}
if (rdp->state >= CONNECTION_STATE_ACTIVE)
if (rdp_get_state(rdp) >= CONNECTION_STATE_ACTIVE)
{
IFCALLRET(client->Activate, client->activated, client);
@ -1573,7 +1577,7 @@ const char* rdp_client_connection_state_string(int state)
}
}
const char* rdp_server_connection_state_string(int state)
const char* rdp_state_string(CONNECTION_STATE state)
{
switch (state)
{
@ -1612,9 +1616,21 @@ const char* rdp_server_connection_state_string(int state)
}
}
int rdp_client_get_state(rdpRdp* rdp)
CONNECTION_STATE rdp_get_state(rdpRdp* rdp)
{
if (!rdp)
return -1;
WINPR_ASSERT(rdp);
return rdp->state;
}
BOOL rdp_set_state(rdpRdp* rdp, CONNECTION_STATE state)
{
WINPR_ASSERT(rdp);
rdp->state = state;
return TRUE;
}
const char* rdp_get_state_string(rdpRdp* rdp)
{
int state = rdp_get_state(rdp);
return rdp_state_string(state);
}

View File

@ -30,25 +30,6 @@
#include <freerdp/settings.h>
#include <freerdp/api.h>
enum CONNECTION_STATE
{
CONNECTION_STATE_INITIAL,
CONNECTION_STATE_NEGO,
CONNECTION_STATE_NLA,
CONNECTION_STATE_MCS_CONNECT,
CONNECTION_STATE_MCS_ERECT_DOMAIN,
CONNECTION_STATE_MCS_ATTACH_USER,
CONNECTION_STATE_MCS_CHANNEL_JOIN,
CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT,
CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE,
CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT,
CONNECTION_STATE_LICENSING,
CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING,
CONNECTION_STATE_CAPABILITIES_EXCHANGE,
CONNECTION_STATE_FINALIZATION,
CONNECTION_STATE_ACTIVE
};
enum CLIENT_CONNECTION_STATE
{
CLIENT_STATE_INITIAL,
@ -66,8 +47,9 @@ FREERDP_LOCAL BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_client_connect_license(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL int rdp_client_transition_to_state(rdpRdp* rdp, int state);
FREERDP_LOCAL const char* rdp_client_connection_state_string(int state);
FREERDP_LOCAL int rdp_client_get_state(rdpRdp* rdp);
FREERDP_LOCAL CONNECTION_STATE rdp_get_state(rdpRdp* rdp);
FREERDP_LOCAL const char* rdp_state_string(CONNECTION_STATE state);
FREERDP_LOCAL BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, wStream* s);
@ -78,6 +60,8 @@ FREERDP_LOCAL BOOL rdp_server_accept_confirm_active(rdpRdp* rdp, wStream* s, UIN
FREERDP_LOCAL BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s);
FREERDP_LOCAL BOOL rdp_server_reactivate(rdpRdp* rdp);
FREERDP_LOCAL int rdp_server_transition_to_state(rdpRdp* rdp, int state);
FREERDP_LOCAL const char* rdp_server_connection_state_string(int state);
FREERDP_LOCAL const char* rdp_get_state_string(rdpRdp* rdp);
FREERDP_LOCAL const char* rdp_client_connection_state_string(int state);
#endif /* FREERDP_LIB_CORE_CONNECTION_H */

View File

@ -948,7 +948,7 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, size_t
goto fail;
rdp = fastpath->rdp;
state = rdp_client_get_state(rdp);
state = rdp_get_state(rdp);
if (state != CONNECTION_STATE_ACTIVE)
{
WLog_WARN(TAG, "[%s] called before activation [%s]", __FUNCTION__,

View File

@ -1135,3 +1135,14 @@ const char* freerdp_nego_get_routing_token(rdpContext* context, DWORD* length)
return (const char*)nego_get_routing_token(context->rdp->nego, length);
}
CONNECTION_STATE freerdp_get_state(rdpContext* context)
{
WINPR_ASSERT(context);
return rdp_get_state(context->rdp);
}
const char* freerdp_state_string(CONNECTION_STATE state)
{
return rdp_state_string(state);
}

View File

@ -203,7 +203,6 @@ static BOOL freerdp_peer_initialize(freerdp_peer* client)
settings->ServerMode = TRUE;
settings->FrameAcknowledge = 0;
settings->LocalConnection = client->local;
rdp->state = CONNECTION_STATE_INITIAL;
if (settings->RdpKeyFile)
{
@ -475,13 +474,13 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
freerdp_peer* client = (freerdp_peer*)extra;
rdpRdp* rdp = client->context->rdp;
switch (rdp->state)
switch (rdp_get_state(rdp))
{
case CONNECTION_STATE_INITIAL:
if (!rdp_server_accept_nego(rdp, s))
{
WLog_ERR(TAG, "%s: %s - rdp_server_accept_nego() fail", __FUNCTION__,
rdp_server_connection_state_string(rdp->state));
rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -510,7 +509,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_server_accept_mcs_connect_initial() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -522,7 +521,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_server_accept_mcs_erect_domain_request() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -534,7 +533,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_server_accept_mcs_attach_user_request() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -546,7 +545,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_server_accept_mcs_channel_join_request() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -560,7 +559,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_server_establish_keys() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
}
@ -578,7 +577,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_recv_client_info() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -606,7 +605,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - callback internal "
"error, aborting",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
case LICENSE_CB_ABORT:
@ -641,7 +640,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_send_demand_active() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -654,7 +653,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"peer_recv_pdu() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
}
@ -670,7 +669,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"peer_recv_pdu() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
return -1;
}
}
@ -681,7 +680,7 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (peer_recv_pdu(client, s) < 0)
{
WLog_ERR(TAG, "%s: %s - peer_recv_pdu() fail", __FUNCTION__,
rdp_server_connection_state_string(rdp->state));
rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -691,15 +690,14 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (peer_recv_pdu(client, s) < 0)
{
WLog_ERR(TAG, "%s: %s - peer_recv_pdu() fail", __FUNCTION__,
rdp_server_connection_state_string(rdp->state));
rdp_state_string(rdp_get_state(rdp)));
return -1;
}
break;
default:
WLog_ERR(TAG, "%s state %d", rdp_server_connection_state_string(rdp->state),
rdp->state);
WLog_ERR(TAG, "%s state %d", rdp_state_string(rdp_get_state(rdp)), rdp_get_state(rdp));
return -1;
}
@ -745,6 +743,245 @@ static BOOL freerdp_peer_send_channel_data(freerdp_peer* client, UINT16 channelI
return rdp_send_channel_data(client->context->rdp, channelId, data, size);
}
static BOOL freerdp_peer_send_server_redirection_pdu(
freerdp_peer* peer, UINT32 sessionId, const char* targetNetAddress, const char* routingToken,
const char* userName, const char* domain, const char* password, const char* targetFQDN,
const char* targetNetBiosName, DWORD tsvUrlLength, const BYTE* tsvUrl,
UINT32 targetNetAddressesCount, const char** targetNetAddresses)
{
wStream* s = rdp_send_stream_pdu_init(peer->context->rdp);
UINT16 length;
UINT32 redirFlags;
UINT32 targetNetAddressLength;
UINT32 loadBalanceInfoLength;
UINT32 userNameLength;
UINT32 domainLength;
UINT32 passwordLength;
UINT32 targetFQDNLength;
UINT32 targetNetBiosNameLength;
UINT32 targetNetAddressesLength;
UINT32* targetNetAddressesWLength;
LPWSTR targetNetAddressW = NULL;
LPWSTR userNameW = NULL;
LPWSTR domainW = NULL;
LPWSTR passwordW = NULL;
LPWSTR targetFQDNW = NULL;
LPWSTR targetNetBiosNameW = NULL;
LPWSTR* targetNetAddressesW = NULL;
length = 12; /* Flags (2) + length (2) + sessionId (4) + redirection flags (4) */
redirFlags = 0;
if (targetNetAddress)
{
redirFlags |= LB_TARGET_NET_ADDRESS;
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)targetNetAddress, -1, &targetNetAddressW, 0);
targetNetAddressLength = (strlen(targetNetAddress) + 1) * sizeof(WCHAR);
length += 4 + targetNetAddressLength;
}
if (routingToken)
{
redirFlags |= LB_LOAD_BALANCE_INFO;
loadBalanceInfoLength =
13 + strlen(routingToken) + 2; /* Add routing token prefix and suffix */
length += 4 + loadBalanceInfoLength;
}
if (userName)
{
redirFlags |= LB_USERNAME;
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)userName, -1, &userNameW, 0);
userNameLength = (strlen(userName) + 1) * sizeof(WCHAR);
length += 4 + userNameLength;
}
if (domain)
{
redirFlags |= LB_DOMAIN;
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)domain, -1, &domainW, 0);
domainLength = (strlen(domain) + 1) * sizeof(WCHAR);
length += 4 + domainLength;
}
if (password)
{
redirFlags |= LB_PASSWORD;
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)password, -1, &passwordW, 0);
passwordLength = (strlen(password) + 1) * sizeof(WCHAR);
length += 4 + passwordLength;
}
if (targetFQDN)
{
redirFlags |= LB_TARGET_FQDN;
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)targetFQDN, -1, &targetFQDNW, 0);
targetFQDNLength = (strlen(targetFQDN) + 1) * sizeof(WCHAR);
length += 4 + targetFQDNLength;
}
if (targetNetBiosName)
{
redirFlags |= LB_TARGET_NETBIOS_NAME;
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)targetNetBiosName, -1, &targetNetBiosNameW, 0);
targetNetBiosNameLength = (strlen(targetNetBiosName) + 1) * sizeof(WCHAR);
length += 4 + targetNetBiosNameLength;
}
if (tsvUrl)
{
redirFlags |= LB_CLIENT_TSV_URL;
length += 4 + tsvUrlLength;
}
if (targetNetAddresses)
{
UINT32 i;
redirFlags |= LB_TARGET_NET_ADDRESSES;
targetNetAddressesLength = 0;
targetNetAddressesW = calloc(targetNetAddressesCount, sizeof(LPWSTR));
targetNetAddressesWLength = calloc(targetNetAddressesCount, sizeof(UINT32));
for (i = 0; i < targetNetAddressesCount; i++)
{
ConvertToUnicode(CP_UTF8, 0, (LPCSTR)targetNetAddresses[i], -1, &targetNetAddressesW[i],
0);
targetNetAddressesWLength[i] = (strlen(targetNetAddresses[i]) + 1) * sizeof(WCHAR);
targetNetAddressesLength += 4 + targetNetAddressesWLength[i];
}
length += 4 + 4 + targetNetAddressesLength;
}
Stream_Write_UINT16(s, 0);
Stream_Write_UINT16(s, SEC_REDIRECTION_PKT);
Stream_Write_UINT16(s, length);
if (!Stream_EnsureRemainingCapacity(s, length))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
goto fail;
}
if (sessionId)
Stream_Write_UINT32(s, sessionId);
else
Stream_Write_UINT32(s, 0);
Stream_Write_UINT32(s, redirFlags);
if (redirFlags & LB_TARGET_NET_ADDRESS)
{
Stream_Write_UINT32(s, targetNetAddressLength);
Stream_Write(s, targetNetAddressW, targetNetAddressLength);
free(targetNetAddressW);
}
if (redirFlags & LB_LOAD_BALANCE_INFO)
{
Stream_Write_UINT32(s, loadBalanceInfoLength);
Stream_Write(s, "Cookie: msts=", 13);
Stream_Write(s, routingToken, strlen(routingToken));
Stream_Write_UINT8(s, 0x0d);
Stream_Write_UINT8(s, 0x0a);
}
if (redirFlags & LB_USERNAME)
{
Stream_Write_UINT32(s, userNameLength);
Stream_Write(s, userNameW, userNameLength);
free(userNameW);
}
if (redirFlags & LB_DOMAIN)
{
Stream_Write_UINT32(s, domainLength);
Stream_Write(s, domainW, domainLength);
free(domainW);
}
if (redirFlags & LB_PASSWORD)
{
Stream_Write_UINT32(s, passwordLength);
Stream_Write(s, passwordW, passwordLength);
free(passwordW);
}
if (redirFlags & LB_TARGET_FQDN)
{
Stream_Write_UINT32(s, targetFQDNLength);
Stream_Write(s, targetFQDNW, targetFQDNLength);
free(targetFQDNW);
}
if (redirFlags & LB_TARGET_NETBIOS_NAME)
{
Stream_Write_UINT32(s, targetNetBiosNameLength);
Stream_Write(s, targetNetBiosNameW, targetNetBiosNameLength);
free(targetNetBiosNameW);
}
if (redirFlags & LB_CLIENT_TSV_URL)
{
Stream_Write_UINT32(s, tsvUrlLength);
Stream_Write(s, tsvUrl, tsvUrlLength);
}
if (redirFlags & LB_TARGET_NET_ADDRESSES)
{
UINT32 i;
Stream_Write_UINT32(s, targetNetAddressesLength);
Stream_Write_UINT32(s, targetNetAddressesCount);
for (i = 0; i < targetNetAddressesCount; i++)
{
Stream_Write_UINT32(s, targetNetAddressesWLength[i]);
Stream_Write(s, targetNetAddressesW[i], targetNetAddressesWLength[i]);
free(targetNetAddressesW[i]);
}
free(targetNetAddressesW);
free(targetNetAddressesWLength);
}
Stream_Write_UINT8(s, 0);
rdp_send_pdu(peer->context->rdp, s, PDU_TYPE_SERVER_REDIRECTION, 0);
return TRUE;
fail:
free(targetNetAddressW);
free(userNameW);
free(domainW);
free(passwordW);
free(targetFQDNW);
free(targetNetBiosNameW);
free(targetNetAddressesWLength);
if (targetNetAddressesCount > 0)
{
UINT32 i;
for (i = 0; i < targetNetAddressesCount; i++)
free(targetNetAddressesW[i]);
free(targetNetAddressesW);
}
return FALSE;
}
static BOOL freerdp_peer_is_write_blocked(freerdp_peer* peer)
{
rdpTransport* transport = peer->context->rdp->transport;
@ -980,6 +1217,7 @@ freerdp_peer* freerdp_peer_new(int sockfd)
client->Close = freerdp_peer_close;
client->Disconnect = freerdp_peer_disconnect;
client->SendChannelData = freerdp_peer_send_channel_data;
client->SendServerRedirection = freerdp_peer_send_server_redirection_pdu;
client->IsWriteBlocked = freerdp_peer_is_write_blocked;
client->DrainOutputBuffer = freerdp_peer_drain_output_buffer;
client->HasMoreToRead = freerdp_peer_has_more_to_read;

View File

@ -1502,13 +1502,14 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
* enters the active state, an auto-detect PDU can be received
* on the MCS message channel.
*/
if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) && (rdp->state < CONNECTION_STATE_ACTIVE))
if ((rdp_get_state(rdp) > CONNECTION_STATE_MCS_CHANNEL_JOIN) &&
(rdp_get_state(rdp) < CONNECTION_STATE_ACTIVE))
{
if (rdp_client_connect_auto_detect(rdp, s))
return 0;
}
switch (rdp->state)
switch (rdp_get_state(rdp))
{
case CONNECTION_STATE_NLA:
if (nla_get_state(rdp->nla) < NLA_STATE_AUTH_INFO)
@ -1516,7 +1517,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (nla_recv_pdu(rdp->nla, s) < 1)
{
WLog_ERR(TAG, "%s: %s - nla_recv_pdu() fail", __FUNCTION__,
rdp_server_connection_state_string(rdp->state));
rdp_state_string(rdp_get_state(rdp)));
return -1;
}
}
@ -1527,7 +1528,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (nego_get_state(rdp->nego) != NEGO_STATE_FINAL)
{
WLog_ERR(TAG, "%s: %s - nego_recv() fail", __FUNCTION__,
rdp_server_connection_state_string(rdp->state));
rdp_state_string(rdp_get_state(rdp)));
return -1;
}
@ -1567,7 +1568,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (!mcs_client_begin(rdp->mcs))
{
WLog_ERR(TAG, "%s: %s - mcs_client_begin() fail", __FUNCTION__,
rdp_server_connection_state_string(rdp->state));
rdp_state_string(rdp_get_state(rdp)));
return -1;
}
}
@ -1618,7 +1619,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_ERR(TAG,
"%s: %s - "
"rdp_client_connect_mcs_channel_join_confirm() fail",
__FUNCTION__, rdp_server_connection_state_string(rdp->state));
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)));
status = -1;
}
@ -1629,7 +1630,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (status < 0)
WLog_DBG(TAG, "%s: %s - rdp_client_connect_license() - %i", __FUNCTION__,
rdp_server_connection_state_string(rdp->state), status);
rdp_state_string(rdp_get_state(rdp)), status);
break;
@ -1640,7 +1641,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
WLog_DBG(TAG,
"%s: %s - "
"rdp_client_connect_demand_active() - %i",
__FUNCTION__, rdp_server_connection_state_string(rdp->state), status);
__FUNCTION__, rdp_state_string(rdp_get_state(rdp)), status);
break;
@ -1655,7 +1656,7 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (status < 0)
WLog_DBG(TAG, "%s: %s - rdp_recv_pdu() - %i", __FUNCTION__,
rdp_server_connection_state_string(rdp->state), status);
rdp_state_string(rdp_get_state(rdp)), status);
break;
@ -1664,13 +1665,13 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
if (status < 0)
WLog_DBG(TAG, "%s: %s - rdp_recv_pdu() - %i", __FUNCTION__,
rdp_server_connection_state_string(rdp->state), status);
rdp_state_string(rdp_get_state(rdp)), status);
break;
default:
WLog_ERR(TAG, "%s: %s state %d", __FUNCTION__,
rdp_server_connection_state_string(rdp->state), rdp->state);
WLog_ERR(TAG, "%s: %s state %d", __FUNCTION__, rdp_state_string(rdp_get_state(rdp)),
rdp_get_state(rdp));
status = -1;
break;
}

View File

@ -132,7 +132,7 @@
struct rdp_rdp
{
int state;
CONNECTION_STATE state;
freerdp* instance;
rdpContext* context;
rdpNla* nla;

View File

@ -94,6 +94,9 @@ struct p_client_context
UINT64 frames_count;
wHashTable* vc_ids; /* channel_name -> channel_id map */
BOOL input_state_sync_pending;
UINT32 input_state;
};
typedef struct p_client_context pClientContext;

View File

@ -23,11 +23,28 @@
#include "pf_context.h"
#include "pf_modules.h"
static BOOL pf_server_check_and_sync_input_state(pClientContext* pc)
{
if (freerdp_get_state(&pc->context) < CONNECTION_STATE_ACTIVE)
return FALSE;
if (pc->input_state_sync_pending)
{
BOOL rc = freerdp_input_send_synchronize_event(pc->context.input, pc->input_state);
if (rc)
pc->input_state_sync_pending = FALSE;
}
return TRUE;
}
static BOOL pf_server_synchronize_event(rdpInput* input, UINT32 flags)
{
pServerContext* ps = (pServerContext*)input->context;
pClientContext* pc = ps->pdata->pc;
return freerdp_input_send_synchronize_event(pc->context.input, flags);
pc->input_state = flags;
pc->input_state_sync_pending = TRUE;
pf_server_check_and_sync_input_state(pc);
return TRUE;
}
static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
@ -37,6 +54,9 @@ static BOOL pf_server_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
proxyConfig* config = ps->pdata->config;
proxyKeyboardEventInfo event;
if (!pf_server_check_and_sync_input_state(pc))
return TRUE;
if (!config->Keyboard)
return TRUE;
@ -55,6 +75,9 @@ static BOOL pf_server_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT
pClientContext* pc = ps->pdata->pc;
proxyConfig* config = ps->pdata->config;
if (!pf_server_check_and_sync_input_state(pc))
return TRUE;
if (!config->Keyboard)
return TRUE;
@ -68,6 +91,9 @@ static BOOL pf_server_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT1
proxyConfig* config = ps->pdata->config;
proxyMouseEventInfo event;
if (!pf_server_check_and_sync_input_state(pc))
return TRUE;
if (!config->Mouse)
return TRUE;
@ -87,6 +113,9 @@ static BOOL pf_server_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16
pClientContext* pc = ps->pdata->pc;
proxyConfig* config = ps->pdata->config;
if (!pf_server_check_and_sync_input_state(pc))
return TRUE;
if (!config->Mouse)
return TRUE;

View File

@ -57,7 +57,7 @@ if (NOT WIN32)
endif()
# Soname versioning
set(RAW_VERSION_STRING "2.8.1")
set(RAW_VERSION_STRING "2.9.0")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@ -82,6 +82,8 @@ else()
set(WINPR_VERSION_FULL "${WINPR_VERSION}")
endif()
option(WITH_INTERNAL_MD4 "Use compiled in md4 hash functions instead of OpenSSL/MBedTLS" OFF)
option(WITH_INTERNAL_MD5 "Use compiled in md5 hash functions instead of OpenSSL/MBedTLS" OFF)
if(NOT IOS)
check_include_files(stdbool.h WINPR_HAVE_STDBOOL_H)
check_include_files(stdint.h WINPR_HAVE_STDINT_H)

View File

@ -22,6 +22,7 @@
#define WINPR_SSL_H
#include <winpr/wtypes.h>
#include <winpr/winpr.h>
#define WINPR_SSL_INIT_DEFAULT 0x00
#define WINPR_SSL_INIT_ALREADY_INITIALIZED 0x01

View File

@ -60,10 +60,13 @@ extern "C"
WINPR_API int _strnicmp(const char* string1, const char* string2, size_t count);
WINPR_API int _wcscmp(const WCHAR* string1, const WCHAR* string2);
WINPR_API int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count);
WINPR_API size_t _wcslen(const WCHAR* str);
WINPR_API size_t _wcsnlen(const WCHAR* str, size_t maxNumberOfElements);
WINPR_API WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch);
WINPR_API WCHAR* _wcschr(const WCHAR* str, WCHAR c);
WINPR_API WCHAR* _wcsrchr(const WCHAR* str, WCHAR c);
@ -73,8 +76,10 @@ extern "C"
#else
#define _wcscmp wcscmp
#define _wcsncmp wcsncmp
#define _wcslen wcslen
#define _wcsnlen wcsnlen
#define _wcsstr wcsstr
#define _wcschr wcschr
#define _wcsrchr wcsrchr

View File

@ -30,6 +30,7 @@ extern "C"
#include <stdarg.h>
#include <winpr/wtypes.h>
#include <winpr/winpr.h>
#include <winpr/synch.h>
#include <winpr/thread.h>

View File

@ -26,6 +26,7 @@
#include <wctype.h>
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/endian.h>
/* String Manipulation (CRT): http://msdn.microsoft.com/en-us/library/f0151s4x.aspx */
@ -97,17 +98,39 @@ int _strnicmp(const char* string1, const char* string2, size_t count)
int _wcscmp(const WCHAR* string1, const WCHAR* string2)
{
WCHAR value1, value2;
WINPR_ASSERT(string1);
WINPR_ASSERT(string2);
while (*string1 && (*string1 == *string2))
while (TRUE)
{
string1++;
string2++;
const WCHAR w1 = *string1++;
const WCHAR w2 = *string2++;
if (w1 != w2)
return (int)w1 - w2;
else if ((w1 == '\0') || (w2 == '\0'))
return (int)w1 - w2;
}
Data_Read_UINT16(string1, value1);
Data_Read_UINT16(string2, value2);
return value1 - value2;
return 0;
}
int _wcsncmp(const WCHAR* string1, const WCHAR* string2, size_t count)
{
WINPR_ASSERT(string1);
WINPR_ASSERT(string2);
for (size_t x = 0; x < count; x++)
{
const WCHAR a = string1[x];
const WCHAR b = string2[x];
if (a != b)
return (int)a - b;
else if ((a == '\0') || (b == '\0'))
return (int)a - b;
}
return 0;
}
/* _wcslen -> wcslen */
@ -116,8 +139,7 @@ size_t _wcslen(const WCHAR* str)
{
const WCHAR* p = (const WCHAR*)str;
if (!p)
return 0;
WINPR_ASSERT(p);
while (*p)
p++;
@ -131,8 +153,7 @@ size_t _wcsnlen(const WCHAR* str, size_t max)
{
size_t x;
if (!str)
return 0;
WINPR_ASSERT(str);
for (x = 0; x < max; x++)
{
@ -143,6 +164,26 @@ size_t _wcsnlen(const WCHAR* str, size_t max)
return x;
}
/* _wcsstr -> wcsstr */
WCHAR* _wcsstr(const WCHAR* str, const WCHAR* strSearch)
{
WINPR_ASSERT(str);
WINPR_ASSERT(strSearch);
if (strSearch[0] == '\0')
return str;
const size_t searchLen = _wcslen(strSearch);
while (*str)
{
if (_wcsncmp(str, strSearch, searchLen) == 0)
return str;
str++;
}
return NULL;
}
/* _wcschr -> wcschr */
WCHAR* _wcschr(const WCHAR* str, WCHAR c)

View File

@ -15,13 +15,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
winpr_module_add(
set(SRCS
hash.c
rand.c
cipher.c
cert.c
crypto.c
crypto.h)
crypto.h
)
if (WITH_INTERNAL_MD4)
list(APPEND SRCS md4.c md4.h)
endif()
if (WITH_INTERNAL_MD5)
list(APPEND SRCS md5.c md5.h)
list(APPEND SRCS hmac_md5.c hmac_md5.h)
endif()
winpr_module_add(
${SRCS}
)
if(OPENSSL_FOUND)
winpr_include_directory_add(${OPENSSL_INCLUDE_DIR})

View File

@ -21,7 +21,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/crypto.h>
#ifdef WITH_OPENSSL
@ -39,6 +39,15 @@
#include <mbedtls/md.h>
#endif
#if defined(WITH_INTERNAL_MD4)
#include "md4.h"
#endif
#if defined(WITH_INTERNAL_MD5)
#include "md5.h"
#include "hmac_md5.h"
#endif
/**
* HMAC
*/
@ -146,41 +155,68 @@ const char* winpr_md_type_to_string(WINPR_MD_TYPE md)
return NULL;
}
struct _winpr_hmac_ctx_private_st
{
WINPR_MD_TYPE md;
#if defined(WITH_INTERNAL_MD5)
WINPR_HMAC_MD5_CTX hmac_md5;
#endif
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac;
#endif
#if defined(WITH_MBEDTLS)
mbedtls_md_context_t hmac;
#endif
};
WINPR_HMAC_CTX* winpr_HMAC_New(void)
{
WINPR_HMAC_CTX* ctx = NULL;
WINPR_HMAC_CTX* ctx = calloc(1, sizeof(WINPR_HMAC_CTX));
if (!ctx)
return NULL;
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = NULL;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
if (!(hmac = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX))))
return NULL;
if (!(ctx->hmac = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX))))
goto fail;
HMAC_CTX_init(hmac);
HMAC_CTX_init(ctx->hmac);
#else
if (!(hmac = HMAC_CTX_new()))
return NULL;
if (!(ctx->hmac = HMAC_CTX_new()))
goto fail;
#endif
ctx = (WINPR_HMAC_CTX*)hmac;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* hmac;
if (!(hmac = (mbedtls_md_context_t*)calloc(1, sizeof(mbedtls_md_context_t))))
return NULL;
mbedtls_md_init(hmac);
ctx = (WINPR_HMAC_CTX*)hmac;
mbedtls_md_init(&ctx->hmac);
#endif
return ctx;
fail:
winpr_HMAC_Free(ctx);
return NULL;
}
BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen)
{
WINPR_ASSERT(ctx);
ctx->md = md;
switch (ctx->md)
{
#if defined(WITH_INTERNAL_MD5)
case WINPR_MD_MD5:
hmac_md5_init(&ctx->hmac_md5, key, keylen);
return TRUE;
#endif
default:
break;
}
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*)ctx;
HMAC_CTX* hmac = ctx->hmac;
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
if (!evp || !hmac)
@ -197,7 +233,7 @@ BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, siz
#endif
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* hmac = (mbedtls_md_context_t*)ctx;
mbedtls_md_context_t* hmac = &ctx->hmac;
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
@ -221,8 +257,21 @@ BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, siz
BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen)
{
WINPR_ASSERT(ctx);
switch (ctx->md)
{
#if defined(WITH_INTERNAL_MD5)
case WINPR_MD_MD5:
hmac_md5_update(&ctx->hmac_md5, input, ilen);
return TRUE;
#endif
default:
break;
}
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*)ctx;
HMAC_CTX* hmac = ctx->hmac;
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
HMAC_Update(hmac, input, ilen); /* no return value on OpenSSL 0.9.x */
@ -234,7 +283,7 @@ BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen)
#endif
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*)ctx;
mbedtls_md_context_t* mdctx = &ctx->hmac;
if (mbedtls_md_hmac_update(mdctx, input, ilen) == 0)
return TRUE;
@ -245,17 +294,23 @@ BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen)
BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen)
{
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx;
WINPR_ASSERT(ctx);
switch (ctx->md)
{
#if defined(WITH_INTERNAL_MD5)
case WINPR_MD_MD5:
if (olen < WINPR_MD5_DIGEST_LENGTH)
return FALSE;
hmac_md5_finalize(&ctx->hmac_md5, output);
return TRUE;
#endif
if (!ctx)
return FALSE;
default:
break;
}
#if defined(WITH_OPENSSL)
hmac = (HMAC_CTX*)ctx;
HMAC_CTX* hmac = ctx->hmac;
#if (OPENSSL_VERSION_NUMBER < 0x10000000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
HMAC_Final(hmac, output, NULL); /* no return value on OpenSSL 0.9.x */
@ -267,7 +322,7 @@ BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen)
#endif
#elif defined(WITH_MBEDTLS)
mdctx = (mbedtls_md_context_t*)ctx;
mbedtls_md_context_t* mdctx = &ctx->hmac;
if (mbedtls_md_hmac_finish(mdctx, output) == 0)
return TRUE;
@ -278,8 +333,11 @@ BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen)
void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
{
if (!ctx)
return;
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*)ctx;
HMAC_CTX* hmac = ctx->hmac;
if (hmac)
{
@ -293,15 +351,14 @@ void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
}
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* hmac = (mbedtls_md_context_t*)ctx;
mbedtls_md_context_t* hmac = &ctx->hmac;
if (hmac)
{
mbedtls_md_free(hmac);
free(hmac);
}
#endif
free(ctx);
}
BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, const BYTE* input, size_t ilen,
@ -332,34 +389,60 @@ out:
* Generic Digest API
*/
WINPR_DIGEST_CTX* winpr_Digest_New(void)
struct _winpr_digest_ctx_private_st
{
WINPR_DIGEST_CTX* ctx = NULL;
WINPR_MD_TYPE md;
#if defined(WITH_INTERNAL_MD4)
WINPR_MD4_CTX md4;
#endif
#if defined(WITH_INTERNAL_MD5)
WINPR_MD5_CTX md5;
#endif
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx;
#endif
#if defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx;
#endif
};
WINPR_DIGEST_CTX* winpr_Digest_New(void)
{
WINPR_DIGEST_CTX* ctx = calloc(1, sizeof(WINPR_DIGEST_CTX));
if (!ctx)
return NULL;
#if defined(WITH_OPENSSL)
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
mdctx = EVP_MD_CTX_create();
ctx->mdctx = EVP_MD_CTX_create();
#else
mdctx = EVP_MD_CTX_new();
ctx->mdctx = EVP_MD_CTX_new();
#endif
ctx = (WINPR_DIGEST_CTX*)mdctx;
if (!ctx->mdctx)
goto fail;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx;
mdctx = (mbedtls_md_context_t*)calloc(1, sizeof(mbedtls_md_context_t));
ctx->mdctx = (mbedtls_md_context_t*)calloc(1, sizeof(mbedtls_md_context_t));
if (mdctx)
mbedtls_md_init(mdctx);
if (!ctx->mdctx)
goto fail;
ctx = (WINPR_DIGEST_CTX*)mdctx;
mbedtls_md_init(ctx->mdctx);
#endif
return ctx;
fail:
winpr_Digest_Free(ctx);
return NULL;
}
#if defined(WITH_OPENSSL)
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
{
EVP_MD_CTX* mdctx = (EVP_MD_CTX*)ctx;
WINPR_ASSERT(ctx);
EVP_MD_CTX* mdctx = ctx->mdctx;
if (!mdctx || !evp)
return FALSE;
@ -373,7 +456,8 @@ static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, const EVP_MD* evp)
#elif defined(WITH_MBEDTLS)
static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*)ctx;
WINPR_ASSERT(ctx);
mbedtls_md_context_t* mdctx = ctx->mdctx;
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
@ -397,15 +481,16 @@ static BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
WINPR_ASSERT(ctx);
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*)ctx;
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
/* Only MD5 is supported for FIPS allow override */
if (md != WINPR_MD_MD5)
return FALSE;
EVP_MD_CTX_set_flags(mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
EVP_MD_CTX_set_flags(ctx->mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
return winpr_Digest_Init_Internal(ctx, evp);
#elif defined(WITH_MBEDTLS)
@ -419,6 +504,25 @@ BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
WINPR_ASSERT(ctx);
ctx->md = md;
switch (md)
{
#if defined(WITH_INTERNAL_MD4)
case WINPR_MD_MD4:
winpr_MD4_Init(&ctx->md4);
return TRUE;
#endif
#if defined(WITH_INTERNAL_MD5)
case WINPR_MD_MD5:
winpr_MD5_Init(&ctx->md5);
return TRUE;
#endif
default:
break;
}
#if defined(WITH_OPENSSL)
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
return winpr_Digest_Init_Internal(ctx, evp);
@ -429,14 +533,32 @@ BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen)
{
WINPR_ASSERT(ctx);
switch (ctx->md)
{
#if defined(WITH_INTERNAL_MD4)
case WINPR_MD_MD4:
winpr_MD4_Update(&ctx->md4, input, ilen);
return TRUE;
#endif
#if defined(WITH_INTERNAL_MD5)
case WINPR_MD_MD5:
winpr_MD5_Update(&ctx->md5, input, ilen);
return TRUE;
#endif
default:
break;
}
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*)ctx;
EVP_MD_CTX* mdctx = ctx->mdctx;
if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*)ctx;
mbedtls_md_context_t* mdctx = ctx->mdctx;
if (mbedtls_md_update(mdctx, input, ilen) != 0)
return FALSE;
@ -447,14 +569,37 @@ BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen)
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen)
{
WINPR_ASSERT(ctx);
switch (ctx->md)
{
#if defined(WITH_INTERNAL_MD4)
case WINPR_MD_MD4:
if (olen < WINPR_MD4_DIGEST_LENGTH)
return FALSE;
winpr_MD4_Final(output, &ctx->md4);
return TRUE;
#endif
#if defined(WITH_INTERNAL_MD5)
case WINPR_MD_MD5:
if (olen < WINPR_MD5_DIGEST_LENGTH)
return FALSE;
winpr_MD5_Final(output, &ctx->md5);
return TRUE;
#endif
default:
break;
}
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*)ctx;
EVP_MD_CTX* mdctx = ctx->mdctx;
if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
return TRUE;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*)ctx;
mbedtls_md_context_t* mdctx = ctx->mdctx;
if (mbedtls_md_finish(mdctx, output) == 0)
return TRUE;
@ -465,29 +610,28 @@ BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen)
void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
{
if (!ctx)
return;
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*)ctx;
if (mdctx)
if (ctx->mdctx)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
EVP_MD_CTX_destroy(mdctx);
EVP_MD_CTX_destroy(ctx->mdctx);
#else
EVP_MD_CTX_free(mdctx);
EVP_MD_CTX_free(ctx->mdctx);
#endif
}
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*)ctx;
if (mdctx)
if (ctx->mdctx)
{
mbedtls_md_free(mdctx);
free(mdctx);
mbedtls_md_free(ctx->mdctx);
free(ctx->mdctx);
}
#endif
free(ctx);
}
BOOL winpr_Digest_Allow_FIPS(WINPR_MD_TYPE md, const BYTE* input, size_t ilen, BYTE* output,

View File

@ -0,0 +1,54 @@
#include <assert.h>
#include "hmac_md5.h"
#include "md5.h"
void hmac_md5_init(WINPR_HMAC_MD5_CTX* ctx, unsigned char* key, size_t key_len)
{
const WINPR_HMAC_MD5_CTX empty = { 0 };
unsigned char k_ipad[KEY_IOPAD_SIZE] = { 0 };
unsigned char k_opad[KEY_IOPAD_SIZE] = { 0 };
assert(ctx);
*ctx = empty;
if (key_len <= KEY_IOPAD_SIZE)
{
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
}
else
{
WINPR_MD5_CTX lctx = { 0 };
winpr_MD5_Init(&lctx);
winpr_MD5_Update(&lctx, key, key_len);
winpr_MD5_Final(k_ipad, &lctx);
memcpy(k_opad, k_ipad, KEY_IOPAD_SIZE);
}
for (size_t i = 0; i < KEY_IOPAD_SIZE; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
winpr_MD5_Init(&ctx->icontext);
winpr_MD5_Update(&ctx->icontext, k_ipad, KEY_IOPAD_SIZE);
winpr_MD5_Init(&ctx->ocontext);
winpr_MD5_Update(&ctx->ocontext, k_opad, KEY_IOPAD_SIZE);
}
void hmac_md5_update(WINPR_HMAC_MD5_CTX* ctx, unsigned char* text, size_t text_len)
{
assert(ctx);
winpr_MD5_Update(&ctx->icontext, text, text_len);
}
void hmac_md5_finalize(WINPR_HMAC_MD5_CTX* ctx, unsigned char* hmac)
{
assert(ctx);
winpr_MD5_Final(hmac, &ctx->icontext);
winpr_MD5_Update(&ctx->ocontext, hmac, 16);
winpr_MD5_Final(hmac, &ctx->ocontext);
}

View File

@ -0,0 +1,19 @@
#ifndef WINPR_HMAC_MD5
#define WINPR_HMAC_MD5
#include <stddef.h>
#include "md5.h"
#define KEY_IOPAD_SIZE 64
typedef struct
{
WINPR_MD5_CTX icontext;
WINPR_MD5_CTX ocontext;
} WINPR_HMAC_MD5_CTX;
void hmac_md5_init(WINPR_HMAC_MD5_CTX* ctx, unsigned char* key, size_t key_len);
void hmac_md5_update(WINPR_HMAC_MD5_CTX* ctx, unsigned char* text, size_t text_len);
void hmac_md5_finalize(WINPR_HMAC_MD5_CTX* ctx, unsigned char* hmac);
#endif

266
winpr/libwinpr/crypto/md4.c Normal file
View File

@ -0,0 +1,266 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD4 Message-Digest Algorithm (RFC 1320).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#include <string.h>
#include "md4.h"
/*
* The basic MD4 functions.
*
* F and G are optimized compared to their RFC 1320 definitions, with the
* optimization for F borrowed from Colin Plumb's MD5 implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/*
* The MD4 transformation for all three rounds.
*/
#define STEP(f, a, b, c, d, x, s) \
(a) += f((b), (c), (d)) + (x); \
(a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s))));
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* winpr_MD4_u32plus. In practice, this problem may occur if these MD4 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD4 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) (*(winpr_MD4_u32plus*)&ptr[(n)*4])
#define GET(n) SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = (winpr_MD4_u32plus)ptr[(n)*4] | ((winpr_MD4_u32plus)ptr[(n)*4 + 1] << 8) | \
((winpr_MD4_u32plus)ptr[(n)*4 + 2] << 16) | \
((winpr_MD4_u32plus)ptr[(n)*4 + 3] << 24))
#define GET(n) (ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static const void* body(WINPR_MD4_CTX* ctx, const void* data, unsigned long size)
{
const unsigned char* ptr;
winpr_MD4_u32plus a, b, c, d;
winpr_MD4_u32plus saved_a, saved_b, saved_c, saved_d;
const winpr_MD4_u32plus ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
ptr = (const unsigned char*)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do
{
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 3)
STEP(F, d, a, b, c, SET(1), 7)
STEP(F, c, d, a, b, SET(2), 11)
STEP(F, b, c, d, a, SET(3), 19)
STEP(F, a, b, c, d, SET(4), 3)
STEP(F, d, a, b, c, SET(5), 7)
STEP(F, c, d, a, b, SET(6), 11)
STEP(F, b, c, d, a, SET(7), 19)
STEP(F, a, b, c, d, SET(8), 3)
STEP(F, d, a, b, c, SET(9), 7)
STEP(F, c, d, a, b, SET(10), 11)
STEP(F, b, c, d, a, SET(11), 19)
STEP(F, a, b, c, d, SET(12), 3)
STEP(F, d, a, b, c, SET(13), 7)
STEP(F, c, d, a, b, SET(14), 11)
STEP(F, b, c, d, a, SET(15), 19)
/* Round 2 */
STEP(G, a, b, c, d, GET(0) + ac1, 3)
STEP(G, d, a, b, c, GET(4) + ac1, 5)
STEP(G, c, d, a, b, GET(8) + ac1, 9)
STEP(G, b, c, d, a, GET(12) + ac1, 13)
STEP(G, a, b, c, d, GET(1) + ac1, 3)
STEP(G, d, a, b, c, GET(5) + ac1, 5)
STEP(G, c, d, a, b, GET(9) + ac1, 9)
STEP(G, b, c, d, a, GET(13) + ac1, 13)
STEP(G, a, b, c, d, GET(2) + ac1, 3)
STEP(G, d, a, b, c, GET(6) + ac1, 5)
STEP(G, c, d, a, b, GET(10) + ac1, 9)
STEP(G, b, c, d, a, GET(14) + ac1, 13)
STEP(G, a, b, c, d, GET(3) + ac1, 3)
STEP(G, d, a, b, c, GET(7) + ac1, 5)
STEP(G, c, d, a, b, GET(11) + ac1, 9)
STEP(G, b, c, d, a, GET(15) + ac1, 13)
/* Round 3 */
STEP(H, a, b, c, d, GET(0) + ac2, 3)
STEP(H, d, a, b, c, GET(8) + ac2, 9)
STEP(H, c, d, a, b, GET(4) + ac2, 11)
STEP(H, b, c, d, a, GET(12) + ac2, 15)
STEP(H, a, b, c, d, GET(2) + ac2, 3)
STEP(H, d, a, b, c, GET(10) + ac2, 9)
STEP(H, c, d, a, b, GET(6) + ac2, 11)
STEP(H, b, c, d, a, GET(14) + ac2, 15)
STEP(H, a, b, c, d, GET(1) + ac2, 3)
STEP(H, d, a, b, c, GET(9) + ac2, 9)
STEP(H, c, d, a, b, GET(5) + ac2, 11)
STEP(H, b, c, d, a, GET(13) + ac2, 15)
STEP(H, a, b, c, d, GET(3) + ac2, 3)
STEP(H, d, a, b, c, GET(11) + ac2, 9)
STEP(H, c, d, a, b, GET(7) + ac2, 11)
STEP(H, b, c, d, a, GET(15) + ac2, 15)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void winpr_MD4_Init(WINPR_MD4_CTX* ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const void* data, unsigned long size)
{
winpr_MD4_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used)
{
available = 64 - used;
if (size < available)
{
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char*)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64)
{
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
void winpr_MD4_Final(unsigned char* result, WINPR_MD4_CTX* ctx)
{
unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8)
{
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}

View File

@ -0,0 +1,46 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD4 Message-Digest Algorithm (RFC 1320).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md4.c for more information.
*/
#if !defined(WINPR_MD4_H)
#define WINPR_MD4_H
#include <winpr/wtypes.h>
/* Any 32-bit or wider unsigned integer data type will do */
typedef UINT32 winpr_MD4_u32plus;
typedef struct
{
winpr_MD4_u32plus lo, hi;
winpr_MD4_u32plus a, b, c, d;
unsigned char buffer[64];
winpr_MD4_u32plus block[16];
} WINPR_MD4_CTX;
extern void winpr_MD4_Init(WINPR_MD4_CTX* ctx);
extern void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const void* data, unsigned long size);
extern void winpr_MD4_Final(unsigned char* result, WINPR_MD4_CTX* ctx);
#endif

287
winpr/libwinpr/crypto/md5.c Normal file
View File

@ -0,0 +1,287 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#include <string.h>
#include "md5.h"
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a)&0xffffffff) >> (32 - (s)))); \
(a) += (b);
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) (*(winpr_MD5_u32plus*)&ptr[(n)*4])
#define GET(n) SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = (winpr_MD5_u32plus)ptr[(n)*4] | ((winpr_MD5_u32plus)ptr[(n)*4 + 1] << 8) | \
((winpr_MD5_u32plus)ptr[(n)*4 + 2] << 16) | \
((winpr_MD5_u32plus)ptr[(n)*4 + 3] << 24))
#define GET(n) (ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static const void* body(WINPR_MD5_CTX* ctx, const void* data, unsigned long size)
{
const unsigned char* ptr;
winpr_MD5_u32plus a, b, c, d;
winpr_MD5_u32plus saved_a, saved_b, saved_c, saved_d;
ptr = (const unsigned char*)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do
{
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void winpr_MD5_Init(WINPR_MD5_CTX* ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const void* data, unsigned long size)
{
winpr_MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used)
{
available = 64 - used;
if (size < available)
{
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char*)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64)
{
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
void winpr_MD5_Final(unsigned char* result, WINPR_MD5_CTX* ctx)
{
unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8)
{
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}

View File

@ -0,0 +1,48 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#if !defined(WINPR_MD5_H)
#define WINPR_MD5_H
#include <winpr/wtypes.h>
/* Any 32-bit or wider unsigned integer data type will do */
typedef UINT32 winpr_MD5_u32plus;
typedef struct
{
winpr_MD5_u32plus lo, hi;
winpr_MD5_u32plus a, b, c, d;
unsigned char buffer[64];
winpr_MD5_u32plus block[16];
} WINPR_MD5_CTX;
extern void winpr_MD5_Init(WINPR_MD5_CTX* ctx);
extern void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const void* data, unsigned long size);
extern void winpr_MD5_Final(unsigned char* result, WINPR_MD5_CTX* ctx);
#endif

View File

@ -11,7 +11,7 @@ static const BYTE TEST_MD5_HASH[] =
static BOOL test_crypto_hash_md5(void)
{
BOOL result = FALSE;
BYTE hash[WINPR_MD5_DIGEST_LENGTH];
BYTE hash[WINPR_MD5_DIGEST_LENGTH] = { 0 };
WINPR_DIGEST_CTX* ctx;
if (!(ctx = winpr_Digest_New()))
@ -64,7 +64,7 @@ static const BYTE TEST_MD4_HASH[] =
static BOOL test_crypto_hash_md4(void)
{
BOOL result = FALSE;
BYTE hash[WINPR_MD4_DIGEST_LENGTH];
BYTE hash[WINPR_MD4_DIGEST_LENGTH] = { 0 };
WINPR_DIGEST_CTX* ctx;
if (!(ctx = winpr_Digest_New()))
@ -117,7 +117,7 @@ static const BYTE TEST_SHA1_HASH[] =
static BOOL test_crypto_hash_sha1(void)
{
BOOL result = FALSE;
BYTE hash[WINPR_SHA1_DIGEST_LENGTH];
BYTE hash[WINPR_SHA1_DIGEST_LENGTH] = { 0 };
WINPR_DIGEST_CTX* ctx;
if (!(ctx = winpr_Digest_New()))
@ -168,11 +168,11 @@ static const char TEST_HMAC_MD5_DATA[] = "Hi There";
static const BYTE TEST_HMAC_MD5_KEY[] =
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
static const BYTE TEST_HMAC_MD5_HASH[] =
"\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d";
"\xb5\x79\x91\xa2\x20\x3d\x49\x2d\x73\xfb\x71\x43\xdf\xc5\x08\x28";
static BOOL test_crypto_hash_hmac_md5(void)
{
BYTE hash[WINPR_MD5_DIGEST_LENGTH];
BYTE hash[WINPR_MD5_DIGEST_LENGTH] = { 0 };
WINPR_HMAC_CTX* ctx;
BOOL result = FALSE;
@ -193,6 +193,12 @@ static BOOL test_crypto_hash_hmac_md5(void)
fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_MD5_DATA,
strnlen(TEST_HMAC_MD5_DATA, sizeof(TEST_HMAC_MD5_DATA))))
{
fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __FUNCTION__);
@ -225,11 +231,11 @@ static const char TEST_HMAC_SHA1_DATA[] = "Hi There";
static const BYTE TEST_HMAC_SHA1_KEY[] =
"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b";
static const BYTE TEST_HMAC_SHA1_HASH[] =
"\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00";
"\xab\x23\x08\x2d\xca\x0c\x75\xea\xca\x60\x09\xc0\xb8\x8c\x2d\xf4\xf4\xbf\x88\xee";
static BOOL test_crypto_hash_hmac_sha1(void)
{
BYTE hash[WINPR_SHA1_DIGEST_LENGTH];
BYTE hash[WINPR_SHA1_DIGEST_LENGTH] = { 0 };
WINPR_HMAC_CTX* ctx;
BOOL result = FALSE;
@ -250,6 +256,12 @@ static BOOL test_crypto_hash_hmac_sha1(void)
fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Update(ctx, (const BYTE*)TEST_HMAC_SHA1_DATA,
strnlen(TEST_HMAC_SHA1_DATA, sizeof(TEST_HMAC_SHA1_DATA))))
{
fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __FUNCTION__);

View File

@ -42,6 +42,12 @@
static BOOL g_winpr_openssl_initialized_by_winpr = FALSE;
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
static OSSL_PROVIDER* s_winpr_openssl_provider_fips = NULL;
static OSSL_PROVIDER* s_winpr_openssl_provider_legacy = NULL;
static OSSL_PROVIDER* s_winpr_openssl_provider_default = NULL;
#endif
/**
* Note from OpenSSL 1.1.0 "CHANGES":
* OpenSSL now uses a new threading API. It is no longer necessary to
@ -249,7 +255,11 @@ static BOOL winpr_enable_fips(DWORD flags)
WLog_DBG(TAG, "Ensuring openssl fips mode is enabled");
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
OSSL_PROVIDER_load(NULL, "fips");
s_winpr_openssl_provider_fips = OSSL_PROVIDER_load(NULL, "fips");
if (s_winpr_openssl_provider_fips == NULL)
{
WLog_WARN(TAG, "OpenSSL FIPS provider failled to load");
}
if (!EVP_default_properties_is_fips_enabled(NULL))
#else
if (FIPS_mode() != 1)
@ -313,8 +323,16 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
/* The legacy provider is needed for MD4. */
OSSL_PROVIDER_load(NULL, "legacy");
OSSL_PROVIDER_load(NULL, "default");
s_winpr_openssl_provider_legacy = OSSL_PROVIDER_load(NULL, "legacy");
if (s_winpr_openssl_provider_legacy == NULL)
{
WLog_WARN(TAG, "OpenSSL LEGACY provider failed to load, no md4 support available!");
}
s_winpr_openssl_provider_default = OSSL_PROVIDER_load(NULL, "default");
if (s_winpr_openssl_provider_default == NULL)
{
WLog_WARN(TAG, "OpenSSL DEFAULT provider failed to load");
}
#endif
g_winpr_openssl_initialized_by_winpr = TRUE;
@ -368,6 +386,11 @@ BOOL winpr_CleanupSSL(DWORD flags)
#endif
}
#endif
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
OSSL_PROVIDER_unload(s_winpr_openssl_provider_fips);
OSSL_PROVIDER_unload(s_winpr_openssl_provider_legacy);
OSSL_PROVIDER_unload(s_winpr_openssl_provider_default);
#endif
return TRUE;
}