mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
[nla] initial server-side remote credential guard support
Adds support for server-side remote credential guard in NLA. When enabled that allows the remote user to connect without shipping credentials in TSCred packets. Instead it will send his TGT encoded with a TGS from the remote server. This way the server is able to populate that TGT in a local credential cache without knowing the user's password. The patch only treats the NLA part and does not contain the associated RDPEAR channel that allows to have the complete interaction to retrieve new access tokens.
This commit is contained in:
parent
20f09b2d34
commit
061148f856
@ -31,6 +31,7 @@
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/ntlm.h>
|
||||
#include <winpr/winsock.h>
|
||||
#include <winpr/secapi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -42,146 +43,157 @@ extern "C"
|
||||
|
||||
typedef BOOL (*psPeerInitialize)(freerdp_peer* peer);
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
WINPR_DEPRECATED_VAR("Use psPeerGetEventHandle instead",
|
||||
typedef BOOL (*psPeerGetFileDescriptor)(freerdp_peer* peer, void** rfds,
|
||||
int* rcount);)
|
||||
WINPR_DEPRECATED_VAR("Use psPeerGetEventHandle instead",
|
||||
typedef BOOL (*psPeerGetFileDescriptor)(freerdp_peer* peer, void** rfds,
|
||||
int* rcount);)
|
||||
#endif
|
||||
typedef HANDLE (*psPeerGetEventHandle)(freerdp_peer* peer);
|
||||
typedef DWORD (*psPeerGetEventHandles)(freerdp_peer* peer, HANDLE* events, DWORD count);
|
||||
typedef HANDLE (*psPeerGetReceiveEventHandle)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerCheckFileDescriptor)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerIsWriteBlocked)(freerdp_peer* peer);
|
||||
typedef int (*psPeerDrainOutputBuffer)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerHasMoreToRead)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerClose)(freerdp_peer* peer);
|
||||
typedef void (*psPeerDisconnect)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerCapabilities)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerPostConnect)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerActivate)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerLogon)(freerdp_peer* peer, const SEC_WINNT_AUTH_IDENTITY* identity,
|
||||
BOOL automatic);
|
||||
typedef BOOL (*psPeerSendServerRedirection)(freerdp_peer* peer, const rdpRedirection* redirection);
|
||||
typedef BOOL (*psPeerAdjustMonitorsLayout)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerClientCapabilities)(freerdp_peer* peer);
|
||||
typedef HANDLE (*psPeerGetEventHandle)(freerdp_peer* peer);
|
||||
typedef DWORD (*psPeerGetEventHandles)(freerdp_peer* peer, HANDLE* events, DWORD count);
|
||||
typedef HANDLE (*psPeerGetReceiveEventHandle)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerCheckFileDescriptor)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerIsWriteBlocked)(freerdp_peer* peer);
|
||||
typedef int (*psPeerDrainOutputBuffer)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerHasMoreToRead)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerClose)(freerdp_peer* peer);
|
||||
typedef void (*psPeerDisconnect)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerRemoteCredentials)(freerdp_peer* peer, KERB_TICKET_LOGON* logonCreds,
|
||||
MSV1_0_SUPPLEMENTAL_CREDENTIAL* suppCreds);
|
||||
typedef BOOL (*psPeerCapabilities)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerPostConnect)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerActivate)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerLogon)(freerdp_peer* peer, const SEC_WINNT_AUTH_IDENTITY* identity,
|
||||
BOOL automatic);
|
||||
typedef BOOL (*psPeerSendServerRedirection)(freerdp_peer* peer,
|
||||
const rdpRedirection* redirection);
|
||||
typedef BOOL (*psPeerAdjustMonitorsLayout)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerClientCapabilities)(freerdp_peer* peer);
|
||||
|
||||
typedef BOOL (*psPeerSendChannelData)(freerdp_peer* peer, UINT16 channelId, const BYTE* data,
|
||||
size_t size);
|
||||
typedef BOOL (*psPeerSendChannelPacket)(freerdp_peer* client, UINT16 channelId, size_t totalSize,
|
||||
UINT32 flags, const BYTE* data, size_t chunkSize);
|
||||
typedef BOOL (*psPeerReceiveChannelData)(freerdp_peer* peer, UINT16 channelId, const BYTE* data,
|
||||
size_t size, UINT32 flags, size_t totalSize);
|
||||
typedef BOOL (*psPeerSendChannelData)(freerdp_peer* peer, UINT16 channelId, const BYTE* data,
|
||||
size_t size);
|
||||
typedef BOOL (*psPeerSendChannelPacket)(freerdp_peer* client, UINT16 channelId,
|
||||
size_t totalSize, UINT32 flags, const BYTE* data,
|
||||
size_t chunkSize);
|
||||
typedef BOOL (*psPeerReceiveChannelData)(freerdp_peer* peer, UINT16 channelId, const BYTE* data,
|
||||
size_t size, UINT32 flags, size_t totalSize);
|
||||
|
||||
typedef HANDLE (*psPeerVirtualChannelOpen)(freerdp_peer* peer, const char* name, UINT32 flags);
|
||||
typedef BOOL (*psPeerVirtualChannelClose)(freerdp_peer* peer, HANDLE hChannel);
|
||||
typedef int (*psPeerVirtualChannelRead)(freerdp_peer* peer, HANDLE hChannel, BYTE* buffer,
|
||||
UINT32 length);
|
||||
typedef int (*psPeerVirtualChannelWrite)(freerdp_peer* peer, HANDLE hChannel, const BYTE* buffer,
|
||||
UINT32 length);
|
||||
typedef void* (*psPeerVirtualChannelGetData)(freerdp_peer* peer, HANDLE hChannel);
|
||||
typedef int (*psPeerVirtualChannelSetData)(freerdp_peer* peer, HANDLE hChannel, void* data);
|
||||
typedef BOOL (*psPeerSetState)(freerdp_peer* peer, CONNECTION_STATE state);
|
||||
typedef BOOL (*psPeerReachedState)(freerdp_peer* peer, CONNECTION_STATE state);
|
||||
typedef HANDLE (*psPeerVirtualChannelOpen)(freerdp_peer* peer, const char* name, UINT32 flags);
|
||||
typedef BOOL (*psPeerVirtualChannelClose)(freerdp_peer* peer, HANDLE hChannel);
|
||||
typedef int (*psPeerVirtualChannelRead)(freerdp_peer* peer, HANDLE hChannel, BYTE* buffer,
|
||||
UINT32 length);
|
||||
typedef int (*psPeerVirtualChannelWrite)(freerdp_peer* peer, HANDLE hChannel,
|
||||
const BYTE* buffer, UINT32 length);
|
||||
typedef void* (*psPeerVirtualChannelGetData)(freerdp_peer* peer, HANDLE hChannel);
|
||||
typedef int (*psPeerVirtualChannelSetData)(freerdp_peer* peer, HANDLE hChannel, void* data);
|
||||
typedef BOOL (*psPeerSetState)(freerdp_peer* peer, CONNECTION_STATE state);
|
||||
typedef BOOL (*psPeerReachedState)(freerdp_peer* peer, CONNECTION_STATE state);
|
||||
|
||||
/** @brief the result of the license callback */
|
||||
typedef enum
|
||||
{
|
||||
LICENSE_CB_INTERNAL_ERROR, /** an internal error happened in the callback */
|
||||
LICENSE_CB_ABORT, /** licensing process failed, abort the connection */
|
||||
LICENSE_CB_IN_PROGRESS, /** incoming packet has been treated, we're waiting for further packets
|
||||
to complete the workflow */
|
||||
LICENSE_CB_COMPLETED /** the licensing workflow has completed, go to next step */
|
||||
} LicenseCallbackResult;
|
||||
/** @brief the result of the license callback */
|
||||
typedef enum
|
||||
{
|
||||
LICENSE_CB_INTERNAL_ERROR, /** an internal error happened in the callback */
|
||||
LICENSE_CB_ABORT, /** licensing process failed, abort the connection */
|
||||
LICENSE_CB_IN_PROGRESS, /** incoming packet has been treated, we're waiting for further
|
||||
packets to complete the workflow */
|
||||
LICENSE_CB_COMPLETED /** the licensing workflow has completed, go to next step */
|
||||
} LicenseCallbackResult;
|
||||
|
||||
typedef LicenseCallbackResult (*psPeerLicenseCallback)(freerdp_peer* peer, wStream* s);
|
||||
typedef LicenseCallbackResult (*psPeerLicenseCallback)(freerdp_peer* peer, wStream* s);
|
||||
|
||||
struct rdp_freerdp_peer
|
||||
{
|
||||
ALIGN64 rdpContext* context;
|
||||
struct rdp_freerdp_peer
|
||||
{
|
||||
ALIGN64 rdpContext* context;
|
||||
|
||||
ALIGN64 int sockfd;
|
||||
ALIGN64 char hostname[50];
|
||||
ALIGN64 int sockfd;
|
||||
ALIGN64 char hostname[50];
|
||||
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
WINPR_DEPRECATED_VAR("Use rdpContext::update instead", ALIGN64 rdpUpdate* update;)
|
||||
WINPR_DEPRECATED_VAR("Use rdpContext::settings instead", ALIGN64 rdpSettings* settings;)
|
||||
WINPR_DEPRECATED_VAR("Use rdpContext::autodetect instead", ALIGN64 rdpAutoDetect* autodetect;)
|
||||
WINPR_DEPRECATED_VAR("Use rdpContext::update instead", ALIGN64 rdpUpdate* update;)
|
||||
WINPR_DEPRECATED_VAR("Use rdpContext::settings instead", ALIGN64 rdpSettings* settings;)
|
||||
WINPR_DEPRECATED_VAR("Use rdpContext::autodetect instead",
|
||||
ALIGN64 rdpAutoDetect* autodetect;)
|
||||
#else
|
||||
UINT64 reservedX[3];
|
||||
#endif
|
||||
|
||||
ALIGN64 void* ContextExtra;
|
||||
ALIGN64 size_t ContextSize;
|
||||
ALIGN64 psPeerContextNew ContextNew;
|
||||
ALIGN64 psPeerContextFree ContextFree;
|
||||
ALIGN64 void* ContextExtra;
|
||||
ALIGN64 size_t ContextSize;
|
||||
ALIGN64 psPeerContextNew ContextNew;
|
||||
ALIGN64 psPeerContextFree ContextFree;
|
||||
|
||||
ALIGN64 psPeerInitialize Initialize;
|
||||
ALIGN64 psPeerInitialize Initialize;
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
WINPR_DEPRECATED_VAR("Use freerdp_peer::GetEventHandle instead",
|
||||
ALIGN64 psPeerGetFileDescriptor GetFileDescriptor;)
|
||||
WINPR_DEPRECATED_VAR("Use freerdp_peer::GetEventHandle instead",
|
||||
ALIGN64 psPeerGetFileDescriptor GetFileDescriptor;)
|
||||
#else
|
||||
UINT64 reserved;
|
||||
#endif
|
||||
ALIGN64 psPeerGetEventHandle GetEventHandle;
|
||||
ALIGN64 psPeerGetReceiveEventHandle GetReceiveEventHandle;
|
||||
ALIGN64 psPeerCheckFileDescriptor CheckFileDescriptor;
|
||||
ALIGN64 psPeerClose Close;
|
||||
ALIGN64 psPeerDisconnect Disconnect;
|
||||
ALIGN64 psPeerGetEventHandle GetEventHandle;
|
||||
ALIGN64 psPeerGetReceiveEventHandle GetReceiveEventHandle;
|
||||
ALIGN64 psPeerCheckFileDescriptor CheckFileDescriptor;
|
||||
ALIGN64 psPeerClose Close;
|
||||
ALIGN64 psPeerDisconnect Disconnect;
|
||||
|
||||
ALIGN64 psPeerCapabilities Capabilities;
|
||||
ALIGN64 psPeerPostConnect PostConnect;
|
||||
ALIGN64 psPeerActivate Activate;
|
||||
ALIGN64 psPeerLogon Logon;
|
||||
ALIGN64 psPeerCapabilities Capabilities;
|
||||
ALIGN64 psPeerPostConnect PostConnect;
|
||||
ALIGN64 psPeerActivate Activate;
|
||||
ALIGN64 psPeerLogon Logon;
|
||||
|
||||
ALIGN64 psPeerSendServerRedirection SendServerRedirection;
|
||||
ALIGN64 psPeerSendServerRedirection SendServerRedirection;
|
||||
|
||||
ALIGN64 psPeerSendChannelData SendChannelData;
|
||||
ALIGN64 psPeerReceiveChannelData ReceiveChannelData;
|
||||
ALIGN64 psPeerSendChannelData SendChannelData;
|
||||
ALIGN64 psPeerReceiveChannelData ReceiveChannelData;
|
||||
|
||||
ALIGN64 psPeerVirtualChannelOpen VirtualChannelOpen;
|
||||
ALIGN64 psPeerVirtualChannelClose VirtualChannelClose;
|
||||
ALIGN64 psPeerVirtualChannelRead VirtualChannelRead;
|
||||
ALIGN64 psPeerVirtualChannelWrite VirtualChannelWrite;
|
||||
ALIGN64 psPeerVirtualChannelGetData VirtualChannelGetData;
|
||||
ALIGN64 psPeerVirtualChannelSetData VirtualChannelSetData;
|
||||
ALIGN64 psPeerVirtualChannelOpen VirtualChannelOpen;
|
||||
ALIGN64 psPeerVirtualChannelClose VirtualChannelClose;
|
||||
ALIGN64 psPeerVirtualChannelRead VirtualChannelRead;
|
||||
ALIGN64 psPeerVirtualChannelWrite VirtualChannelWrite;
|
||||
ALIGN64 psPeerVirtualChannelGetData VirtualChannelGetData;
|
||||
ALIGN64 psPeerVirtualChannelSetData VirtualChannelSetData;
|
||||
|
||||
ALIGN64 int pId;
|
||||
ALIGN64 UINT32 ack_frame_id;
|
||||
ALIGN64 BOOL local;
|
||||
ALIGN64 BOOL connected;
|
||||
ALIGN64 BOOL activated;
|
||||
ALIGN64 BOOL authenticated;
|
||||
ALIGN64 SEC_WINNT_AUTH_IDENTITY identity;
|
||||
ALIGN64 int pId;
|
||||
ALIGN64 UINT32 ack_frame_id;
|
||||
ALIGN64 BOOL local;
|
||||
ALIGN64 BOOL connected;
|
||||
ALIGN64 BOOL activated;
|
||||
ALIGN64 BOOL authenticated;
|
||||
ALIGN64 SEC_WINNT_AUTH_IDENTITY identity;
|
||||
|
||||
ALIGN64 psPeerIsWriteBlocked IsWriteBlocked;
|
||||
ALIGN64 psPeerDrainOutputBuffer DrainOutputBuffer;
|
||||
ALIGN64 psPeerHasMoreToRead HasMoreToRead;
|
||||
ALIGN64 psPeerGetEventHandles GetEventHandles;
|
||||
ALIGN64 psPeerAdjustMonitorsLayout AdjustMonitorsLayout;
|
||||
ALIGN64 psPeerClientCapabilities ClientCapabilities;
|
||||
ALIGN64 psPeerIsWriteBlocked IsWriteBlocked;
|
||||
ALIGN64 psPeerDrainOutputBuffer DrainOutputBuffer;
|
||||
ALIGN64 psPeerHasMoreToRead HasMoreToRead;
|
||||
ALIGN64 psPeerGetEventHandles GetEventHandles;
|
||||
ALIGN64 psPeerAdjustMonitorsLayout AdjustMonitorsLayout;
|
||||
ALIGN64 psPeerClientCapabilities ClientCapabilities;
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
WINPR_DEPRECATED_VAR("Use freerdp_peer::SspiNtlmHashCallback instead",
|
||||
ALIGN64 psPeerComputeNtlmHash ComputeNtlmHash;)
|
||||
WINPR_DEPRECATED_VAR("Use freerdp_peer::SspiNtlmHashCallback instead",
|
||||
ALIGN64 psPeerComputeNtlmHash ComputeNtlmHash;)
|
||||
#else
|
||||
UINT64 reserved2;
|
||||
#endif
|
||||
ALIGN64 psPeerLicenseCallback LicenseCallback;
|
||||
ALIGN64 psPeerLicenseCallback LicenseCallback;
|
||||
|
||||
ALIGN64 psPeerSendChannelPacket SendChannelPacket;
|
||||
ALIGN64 psPeerSendChannelPacket SendChannelPacket;
|
||||
|
||||
/**
|
||||
* @brief SetState Function pointer allowing to manually set the state of the
|
||||
* internal state machine.
|
||||
*
|
||||
* This is useful if certain parts of a RDP connection must be skipped (e.g.
|
||||
* when replaying a RDP connection dump the authentication/negotiate parts
|
||||
* must be skipped)
|
||||
*
|
||||
* \note Must be called after \b Initialize as that also modifies the state.
|
||||
*/
|
||||
ALIGN64 psPeerSetState SetState;
|
||||
ALIGN64 psPeerReachedState ReachedState;
|
||||
ALIGN64 psSspiNtlmHashCallback SspiNtlmHashCallback;
|
||||
};
|
||||
/**
|
||||
* @brief SetState Function pointer allowing to manually set the state of the
|
||||
* internal state machine.
|
||||
*
|
||||
* This is useful if certain parts of a RDP connection must be skipped (e.g.
|
||||
* when replaying a RDP connection dump the authentication/negotiate parts
|
||||
* must be skipped)
|
||||
*
|
||||
* \note Must be called after \b Initialize as that also modifies the state.
|
||||
*/
|
||||
ALIGN64 psPeerSetState SetState;
|
||||
ALIGN64 psPeerReachedState ReachedState;
|
||||
ALIGN64 psSspiNtlmHashCallback SspiNtlmHashCallback;
|
||||
/**
|
||||
* @brief RemoteCredentials Function pointer that will be called when remote
|
||||
* credentials guard are used by the peer and we receive the logonCreds (kerberos)
|
||||
* and supplementary creds (NTLM).
|
||||
*/
|
||||
ALIGN64 psPeerRemoteCredentials RemoteCredentials;
|
||||
};
|
||||
|
||||
FREERDP_API BOOL freerdp_peer_context_new(freerdp_peer* client);
|
||||
FREERDP_API BOOL freerdp_peer_context_new_ex(freerdp_peer* client, const rdpSettings* settings);
|
||||
|
@ -651,6 +651,7 @@ extern "C"
|
||||
#define FreeRDP_RdstlsSecurity (1111)
|
||||
#define FreeRDP_AadSecurity (1112)
|
||||
#define FreeRDP_WinSCardModule (1113)
|
||||
#define FreeRDP_RemoteCredentialGuard (1114)
|
||||
#define FreeRDP_MstscCookieMode (1152)
|
||||
#define FreeRDP_CookieMaxLength (1153)
|
||||
#define FreeRDP_PreconnectionId (1154)
|
||||
@ -1185,7 +1186,8 @@ extern "C"
|
||||
ALIGN64 BOOL RdstlsSecurity; /* 1111 */
|
||||
ALIGN64 BOOL AadSecurity; /* 1112 */
|
||||
ALIGN64 char* WinSCardModule; /* 1113 */
|
||||
UINT64 padding1152[1152 - 1114]; /* 1114 */
|
||||
ALIGN64 BOOL RemoteCredentialGuard; /* 1114 */
|
||||
UINT64 padding1152[1152 - 1115]; /* 1115 */
|
||||
|
||||
/* Connection Cookie */
|
||||
ALIGN64 BOOL MstscCookieMode; /* 1152 */
|
||||
@ -1491,8 +1493,8 @@ extern "C"
|
||||
* If used by an implementation ensure proper state resync after reenabling
|
||||
* input
|
||||
*/
|
||||
ALIGN64 BOOL SuspendInput; /* 2636 */
|
||||
ALIGN64 char* KeyboardPipeName; /* 2637 */
|
||||
ALIGN64 BOOL SuspendInput; /* 2636 */
|
||||
ALIGN64 char* KeyboardPipeName; /* 2637 */
|
||||
ALIGN64 BOOL HasRelativeMouseEvent; /* 2638 */
|
||||
ALIGN64 BOOL HasQoeEvent; /* 2639 */
|
||||
UINT64 padding2688[2688 - 2640]; /* 2640 */
|
||||
@ -1680,20 +1682,20 @@ extern "C"
|
||||
ALIGN64 BOOL SupportDynamicChannels; /* 5059 */
|
||||
UINT64 padding5184[5184 - 5060]; /* 5060 */
|
||||
|
||||
ALIGN64 BOOL SupportEchoChannel; /* 5184 */
|
||||
ALIGN64 BOOL SupportDisplayControl; /* 5185 */
|
||||
ALIGN64 BOOL SupportGeometryTracking; /* 5186 */
|
||||
ALIGN64 BOOL SupportSSHAgentChannel; /* 5187 */
|
||||
ALIGN64 BOOL SupportVideoOptimized; /* 5188 */
|
||||
ALIGN64 char* RDP2TCPArgs; /* 5189 */
|
||||
ALIGN64 BOOL TcpKeepAlive; /* 5190 */
|
||||
ALIGN64 UINT32 TcpKeepAliveRetries; /* 5191 */
|
||||
ALIGN64 UINT32 TcpKeepAliveDelay; /* 5192 */
|
||||
ALIGN64 UINT32 TcpKeepAliveInterval; /* 5193 */
|
||||
ALIGN64 UINT32 TcpAckTimeout; /* 5194 */
|
||||
ALIGN64 char* ActionScript; /* 5195 */
|
||||
ALIGN64 UINT32 Floatbar; /* 5196 */
|
||||
ALIGN64 UINT32 TcpConnectTimeout; /* 5197 */
|
||||
ALIGN64 BOOL SupportEchoChannel; /* 5184 */
|
||||
ALIGN64 BOOL SupportDisplayControl; /* 5185 */
|
||||
ALIGN64 BOOL SupportGeometryTracking; /* 5186 */
|
||||
ALIGN64 BOOL SupportSSHAgentChannel; /* 5187 */
|
||||
ALIGN64 BOOL SupportVideoOptimized; /* 5188 */
|
||||
ALIGN64 char* RDP2TCPArgs; /* 5189 */
|
||||
ALIGN64 BOOL TcpKeepAlive; /* 5190 */
|
||||
ALIGN64 UINT32 TcpKeepAliveRetries; /* 5191 */
|
||||
ALIGN64 UINT32 TcpKeepAliveDelay; /* 5192 */
|
||||
ALIGN64 UINT32 TcpKeepAliveInterval; /* 5193 */
|
||||
ALIGN64 UINT32 TcpAckTimeout; /* 5194 */
|
||||
ALIGN64 char* ActionScript; /* 5195 */
|
||||
ALIGN64 UINT32 Floatbar; /* 5196 */
|
||||
ALIGN64 UINT32 TcpConnectTimeout; /* 5197 */
|
||||
ALIGN64 UINT32 FakeMouseMotionInterval; /* 5198 */
|
||||
UINT64 padding5312[5312 - 5199]; /* 5199 */
|
||||
|
||||
|
@ -465,6 +465,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_RemoteConsoleAudio:
|
||||
return settings->RemoteConsoleAudio;
|
||||
|
||||
case FreeRDP_RemoteCredentialGuard:
|
||||
return settings->RemoteCredentialGuard;
|
||||
|
||||
case FreeRDP_RemoteFxCodec:
|
||||
return settings->RemoteFxCodec;
|
||||
|
||||
@ -1182,6 +1185,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val)
|
||||
settings->RemoteConsoleAudio = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteCredentialGuard:
|
||||
settings->RemoteCredentialGuard = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_RemoteFxCodec:
|
||||
settings->RemoteFxCodec = cnv.c;
|
||||
break;
|
||||
|
@ -192,6 +192,7 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_RemoteAssistanceRequestControl, FREERDP_SETTINGS_TYPE_BOOL,
|
||||
"FreeRDP_RemoteAssistanceRequestControl" },
|
||||
{ FreeRDP_RemoteConsoleAudio, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_RemoteConsoleAudio" },
|
||||
{ FreeRDP_RemoteCredentialGuard, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_RemoteCredentialGuard" },
|
||||
{ FreeRDP_RemoteFxCodec, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_RemoteFxCodec" },
|
||||
{ FreeRDP_RemoteFxImageCodec, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_RemoteFxImageCodec" },
|
||||
{ FreeRDP_RemoteFxOnly, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_RemoteFxOnly" },
|
||||
|
@ -60,6 +60,9 @@ struct rdp_nego
|
||||
BOOL NegotiateSecurityLayer;
|
||||
BOOL EnabledProtocols[32];
|
||||
BOOL RestrictedAdminModeRequired;
|
||||
BOOL RemoteCredsGuardRequired;
|
||||
BOOL RemoteCredsGuardActive;
|
||||
BOOL RemoteCredsGuardSupported;
|
||||
BOOL GatewayEnabled;
|
||||
BOOL GatewayBypassLocal;
|
||||
BOOL ConnectChildSession;
|
||||
@ -1112,6 +1115,9 @@ BOOL nego_send_negotiation_request(rdpNego* nego)
|
||||
if (nego->RestrictedAdminModeRequired)
|
||||
flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
|
||||
|
||||
if (nego->RemoteCredsGuardRequired)
|
||||
flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
|
||||
|
||||
Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
|
||||
Stream_Write_UINT8(s, flags);
|
||||
Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */
|
||||
@ -1221,9 +1227,17 @@ BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
|
||||
|
||||
if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
|
||||
{
|
||||
WLog_ERR(TAG, "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED: FreeRDP does "
|
||||
"not support Remote Credential Guard");
|
||||
return FALSE;
|
||||
if (!nego->RemoteCredsGuardSupported)
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_INFO(TAG, "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
|
||||
}
|
||||
nego->RemoteCredsGuardActive = TRUE;
|
||||
}
|
||||
|
||||
Stream_Read_UINT16(s, length);
|
||||
@ -1418,6 +1432,12 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_SupportGraphicsPipeline))
|
||||
flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_RestrictedAdminModeRequired))
|
||||
flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
|
||||
|
||||
if (nego->RemoteCredsGuardSupported)
|
||||
flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
|
||||
|
||||
/* RDP_NEG_DATA must be present for TLS, NLA, RDP and RDSTLS */
|
||||
Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
|
||||
Stream_Write_UINT8(s, flags); /* flags */
|
||||
@ -1648,6 +1668,28 @@ void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdmin
|
||||
nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
|
||||
}
|
||||
|
||||
void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
|
||||
{
|
||||
WINPR_ASSERT(nego);
|
||||
|
||||
WLog_DBG(TAG, "Enabling remoteCredentialGuards: %s", enabled ? "TRUE" : "FALSE");
|
||||
nego->RemoteCredsGuardRequired = enabled;
|
||||
}
|
||||
|
||||
void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
|
||||
{
|
||||
WINPR_ASSERT(nego);
|
||||
|
||||
nego->RemoteCredsGuardSupported = enabled;
|
||||
}
|
||||
|
||||
BOOL nego_get_remoteCredentialGuard(rdpNego* nego)
|
||||
{
|
||||
WINPR_ASSERT(nego);
|
||||
|
||||
return nego->RemoteCredsGuardActive;
|
||||
}
|
||||
|
||||
void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
|
||||
{
|
||||
WINPR_ASSERT(nego);
|
||||
|
@ -114,6 +114,9 @@ FREERDP_LOCAL BOOL nego_set_target(rdpNego* nego, const char* hostname, UINT16 p
|
||||
FREERDP_LOCAL void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer);
|
||||
FREERDP_LOCAL void nego_set_restricted_admin_mode_required(rdpNego* nego,
|
||||
BOOL RestrictedAdminModeRequired);
|
||||
FREERDP_LOCAL void nego_set_RCG_required(rdpNego* nego, BOOL enabled);
|
||||
FREERDP_LOCAL void nego_set_RCG_supported(rdpNego* nego, BOOL enabled);
|
||||
FREERDP_LOCAL BOOL nego_get_remoteCredentialGuard(rdpNego* nego);
|
||||
FREERDP_LOCAL void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled);
|
||||
FREERDP_LOCAL void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled);
|
||||
FREERDP_LOCAL void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal);
|
||||
|
@ -40,8 +40,11 @@
|
||||
#include <winpr/cred.h>
|
||||
#include <winpr/debug.h>
|
||||
#include <winpr/asn1.h>
|
||||
#include <winpr/secapi.h>
|
||||
|
||||
#include "../crypto/tls.h"
|
||||
#include "nego.h"
|
||||
#include "rdp.h"
|
||||
#include "nla.h"
|
||||
#include "utils.h"
|
||||
#include "credssp_auth.h"
|
||||
@ -336,6 +339,9 @@ static BOOL nla_client_setup_identity(rdpNla* nla)
|
||||
if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
|
||||
PromptPassword = FALSE;
|
||||
}
|
||||
|
||||
if (settings->RemoteCredentialGuard)
|
||||
PromptPassword = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1134,6 +1140,96 @@ static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* setting
|
||||
return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
|
||||
}
|
||||
|
||||
static BOOL nla_read_KERB_TICKET_LOGON(rdpNla* nla, wStream* s, KERB_TICKET_LOGON* ticket)
|
||||
{
|
||||
/* mysterious extra 16 bytes before TGS/TGT content */
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT32(s, ticket->MessageType);
|
||||
Stream_Read_UINT32(s, ticket->Flags);
|
||||
Stream_Read_UINT32(s, ticket->ServiceTicketLength);
|
||||
Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
|
||||
|
||||
if (ticket->MessageType != KerbTicketLogon)
|
||||
{
|
||||
WLog_ERR(TAG, "Not a KerbTicketLogon");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(
|
||||
TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
|
||||
return FALSE;
|
||||
|
||||
/* mysterious 16 bytes in the way, maybe they would need to be interpreted... */
|
||||
Stream_Seek(s, 16);
|
||||
|
||||
/*WLog_INFO(TAG, "TGS");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE), ticket->ServiceTicketLength);*/
|
||||
ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
|
||||
Stream_Seek(s, ticket->ServiceTicketLength);
|
||||
|
||||
/*WLog_INFO(TAG, "TGT");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE),
|
||||
ticket->TicketGrantingTicketLength);*/
|
||||
ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** @brief kind of RCG credentials */
|
||||
typedef enum
|
||||
{
|
||||
RCG_TYPE_KERB,
|
||||
RCG_TYPE_NTLM
|
||||
} RemoteGuardPackageCredType;
|
||||
|
||||
static BOOL nla_read_TSRemoteGuardPackageCred(rdpNla* nla, WinPrAsn1Decoder* dec,
|
||||
RemoteGuardPackageCredType* credsType,
|
||||
wStream* payload)
|
||||
{
|
||||
WinPrAsn1_OctetString packageName = { 0 };
|
||||
WinPrAsn1_OctetString credBuffer = { 0 };
|
||||
BOOL error = FALSE;
|
||||
char packageNameStr[100] = { 0 };
|
||||
|
||||
/* packageName [0] OCTET STRING */
|
||||
if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
|
||||
return TRUE;
|
||||
|
||||
ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len / sizeof(WCHAR),
|
||||
packageNameStr, 100);
|
||||
WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
|
||||
|
||||
/* credBuffer [1] OCTET STRING, */
|
||||
if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
|
||||
return TRUE;
|
||||
|
||||
if (_stricmp(packageNameStr, "Kerberos") == 0)
|
||||
{
|
||||
*credsType = RCG_TYPE_KERB;
|
||||
}
|
||||
else if (_stricmp(packageNameStr, "NTLM") == 0)
|
||||
{
|
||||
*credsType = RCG_TYPE_NTLM;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** @brief kind of TSCreds */
|
||||
typedef enum
|
||||
{
|
||||
TSCREDS_USER_PASSWD = 1,
|
||||
TSCREDS_SMARTCARD = 2,
|
||||
TSCREDS_REMOTEGUARD = 6
|
||||
} TsCredentialsType;
|
||||
|
||||
static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
{
|
||||
WinPrAsn1Decoder dec = { 0 };
|
||||
@ -1141,6 +1237,7 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
WinPrAsn1_OctetString credentials = { 0 };
|
||||
BOOL error = FALSE;
|
||||
WinPrAsn1_INTEGER credType = -1;
|
||||
BOOL ret = true;
|
||||
|
||||
WINPR_ASSERT(nla);
|
||||
WINPR_ASSERT(data);
|
||||
@ -1163,10 +1260,16 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
|
||||
|
||||
rdpSettings* settings = nla->rdpcontext->settings;
|
||||
if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
|
||||
credType != TSCREDS_REMOTEGUARD)
|
||||
{
|
||||
WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (credType)
|
||||
{
|
||||
case 1:
|
||||
case TSCREDS_USER_PASSWD:
|
||||
{
|
||||
/* TSPasswordCreds */
|
||||
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
|
||||
@ -1184,7 +1287,7 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
/* password [2] OCTET STRING */
|
||||
return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
|
||||
}
|
||||
case 2:
|
||||
case TSCREDS_SMARTCARD:
|
||||
{
|
||||
/* TSSmartCardCreds */
|
||||
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
|
||||
@ -1210,12 +1313,78 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
/* domainHint [3] OCTET STRING OPTIONAL */
|
||||
return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
|
||||
}
|
||||
case TSCREDS_REMOTEGUARD:
|
||||
{
|
||||
/* TSRemoteGuardCreds */
|
||||
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
|
||||
return FALSE;
|
||||
|
||||
/* logonCred[0] TSRemoteGuardPackageCred */
|
||||
BOOL error = FALSE;
|
||||
KERB_TICKET_LOGON kerbLogon;
|
||||
WinPrAsn1Decoder logonCredsSeq = { 0 };
|
||||
if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
|
||||
return FALSE;
|
||||
|
||||
RemoteGuardPackageCredType logonCredsType;
|
||||
wStream logonPayload;
|
||||
if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
|
||||
&logonPayload))
|
||||
return FALSE;
|
||||
if (logonCredsType != RCG_TYPE_KERB)
|
||||
{
|
||||
WLog_ERR(TAG, "logonCred must be some Kerberos creds");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
|
||||
{
|
||||
WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
|
||||
MSV1_0_SUPPLEMENTAL_CREDENTIAL ntlmCreds;
|
||||
MSV1_0_SUPPLEMENTAL_CREDENTIAL* suppCreds = NULL;
|
||||
WinPrAsn1Decoder suppCredsSeq = { 0 };
|
||||
|
||||
if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq))
|
||||
{
|
||||
WinPrAsn1Decoder ntlmCredsSeq = { 0 };
|
||||
if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
|
||||
return FALSE;
|
||||
|
||||
RemoteGuardPackageCredType suppCredsType;
|
||||
wStream ntlmPayload;
|
||||
if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
|
||||
&ntlmPayload))
|
||||
return FALSE;
|
||||
|
||||
if (suppCredsType != RCG_TYPE_NTLM)
|
||||
{
|
||||
WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* TODO: suppCreds = &ntlmCreds; and parse NTLM creds */
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid supplementalCreds");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
freerdp_peer* peer = nla->rdpcontext->peer;
|
||||
ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WLog_DBG(TAG, "TSCredentials type " PRIu32 " not supported for now", credType);
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1231,7 +1400,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
|
||||
WinPrAsn1Encoder* enc = NULL;
|
||||
size_t length = 0;
|
||||
wStream s = { 0 };
|
||||
int credType = -1;
|
||||
TsCredentialsType credType;
|
||||
|
||||
WINPR_ASSERT(nla);
|
||||
WINPR_ASSERT(nla->rdpcontext);
|
||||
@ -1239,6 +1408,13 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
|
||||
rdpSettings* settings = nla->rdpcontext->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (settings->RemoteCredentialGuard)
|
||||
credType = TSCREDS_REMOTEGUARD;
|
||||
else if (settings->SmartcardLogon)
|
||||
credType = TSCREDS_SMARTCARD;
|
||||
else
|
||||
credType = TSCREDS_USER_PASSWD;
|
||||
|
||||
enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
|
||||
if (!enc)
|
||||
return FALSE;
|
||||
@ -1248,105 +1424,112 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
|
||||
goto out;
|
||||
|
||||
/* credType [0] INTEGER */
|
||||
credType = settings->SmartcardLogon ? 2 : 1;
|
||||
if (!WinPrAsn1EncContextualInteger(enc, 0, credType))
|
||||
if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
|
||||
goto out;
|
||||
|
||||
/* credentials [1] OCTET STRING */
|
||||
if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
|
||||
goto out;
|
||||
|
||||
if (settings->SmartcardLogon)
|
||||
switch (credType)
|
||||
{
|
||||
struct
|
||||
case TSCREDS_SMARTCARD:
|
||||
{
|
||||
WinPrAsn1_tagId tag;
|
||||
size_t setting_id;
|
||||
} cspData_fields[] = { { 1, FreeRDP_CardName },
|
||||
{ 2, FreeRDP_ReaderName },
|
||||
{ 3, FreeRDP_ContainerName },
|
||||
{ 4, FreeRDP_CspName } };
|
||||
WinPrAsn1_OctetString octet_string = { 0 };
|
||||
|
||||
/* TSSmartCardCreds */
|
||||
if (!WinPrAsn1EncSeqContainer(enc))
|
||||
goto out;
|
||||
|
||||
/* pin [0] OCTET STRING */
|
||||
size_t ss;
|
||||
octet_string.data =
|
||||
(BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
|
||||
octet_string.len = ss * sizeof(WCHAR);
|
||||
const BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
|
||||
free(octet_string.data);
|
||||
if (!res)
|
||||
goto out;
|
||||
|
||||
/* cspData [1] SEQUENCE */
|
||||
if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
|
||||
goto out;
|
||||
|
||||
/* keySpec [0] INTEGER */
|
||||
if (!WinPrAsn1EncContextualInteger(enc, 0,
|
||||
freerdp_settings_get_uint32(settings, FreeRDP_KeySpec)))
|
||||
goto out;
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
|
||||
settings, cspData_fields[i].setting_id, &len);
|
||||
octet_string.len = len * sizeof(WCHAR);
|
||||
if (octet_string.len)
|
||||
struct
|
||||
{
|
||||
const BOOL res2 = WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag,
|
||||
&octet_string) > 0;
|
||||
free(octet_string.data);
|
||||
if (!res2)
|
||||
goto out;
|
||||
WinPrAsn1_tagId tag;
|
||||
size_t setting_id;
|
||||
} cspData_fields[] = { { 1, FreeRDP_CardName },
|
||||
{ 2, FreeRDP_ReaderName },
|
||||
{ 3, FreeRDP_ContainerName },
|
||||
{ 4, FreeRDP_CspName } };
|
||||
WinPrAsn1_OctetString octet_string = { 0 };
|
||||
|
||||
/* TSSmartCardCreds */
|
||||
if (!WinPrAsn1EncSeqContainer(enc))
|
||||
goto out;
|
||||
|
||||
/* pin [0] OCTET STRING */
|
||||
size_t ss;
|
||||
octet_string.data =
|
||||
(BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
|
||||
octet_string.len = ss * sizeof(WCHAR);
|
||||
const BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
|
||||
free(octet_string.data);
|
||||
if (!res)
|
||||
goto out;
|
||||
|
||||
/* cspData [1] SEQUENCE */
|
||||
if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
|
||||
goto out;
|
||||
|
||||
/* keySpec [0] INTEGER */
|
||||
if (!WinPrAsn1EncContextualInteger(
|
||||
enc, 0, freerdp_settings_get_uint32(settings, FreeRDP_KeySpec)))
|
||||
goto out;
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
|
||||
settings, cspData_fields[i].setting_id, &len);
|
||||
octet_string.len = len * sizeof(WCHAR);
|
||||
if (octet_string.len)
|
||||
{
|
||||
const BOOL res2 = WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag,
|
||||
&octet_string) > 0;
|
||||
free(octet_string.data);
|
||||
if (!res2)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* End cspData */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
|
||||
/* End TSSmartCardCreds */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
/* End cspData */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
|
||||
/* End TSSmartCardCreds */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
WinPrAsn1_OctetString username = { 0 };
|
||||
WinPrAsn1_OctetString domain = { 0 };
|
||||
WinPrAsn1_OctetString password = { 0 };
|
||||
|
||||
/* TSPasswordCreds */
|
||||
if (!WinPrAsn1EncSeqContainer(enc))
|
||||
goto out;
|
||||
|
||||
if (!settings->DisableCredentialsDelegation && nla->identity)
|
||||
case TSCREDS_USER_PASSWD:
|
||||
{
|
||||
username.len = nla->identity->UserLength * sizeof(WCHAR);
|
||||
username.data = (BYTE*)nla->identity->User;
|
||||
WinPrAsn1_OctetString username = { 0 };
|
||||
WinPrAsn1_OctetString domain = { 0 };
|
||||
WinPrAsn1_OctetString password = { 0 };
|
||||
|
||||
domain.len = nla->identity->DomainLength * sizeof(WCHAR);
|
||||
domain.data = (BYTE*)nla->identity->Domain;
|
||||
/* TSPasswordCreds */
|
||||
if (!WinPrAsn1EncSeqContainer(enc))
|
||||
goto out;
|
||||
|
||||
password.len = nla->identity->PasswordLength * sizeof(WCHAR);
|
||||
password.data = (BYTE*)nla->identity->Password;
|
||||
if (!settings->DisableCredentialsDelegation && nla->identity)
|
||||
{
|
||||
username.len = nla->identity->UserLength * sizeof(WCHAR);
|
||||
username.data = (BYTE*)nla->identity->User;
|
||||
|
||||
domain.len = nla->identity->DomainLength * sizeof(WCHAR);
|
||||
domain.data = (BYTE*)nla->identity->Domain;
|
||||
|
||||
password.len = nla->identity->PasswordLength * sizeof(WCHAR);
|
||||
password.data = (BYTE*)nla->identity->Password;
|
||||
}
|
||||
|
||||
if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
|
||||
goto out;
|
||||
if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
|
||||
goto out;
|
||||
if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
|
||||
goto out;
|
||||
|
||||
/* End TSPasswordCreds */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
|
||||
goto out;
|
||||
if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
|
||||
goto out;
|
||||
if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
|
||||
goto out;
|
||||
|
||||
/* End TSPasswordCreds */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
case TSCREDS_REMOTEGUARD:
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1364,8 +1547,8 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
|
||||
}
|
||||
|
||||
Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
|
||||
if (WinPrAsn1EncToStream(enc, &s))
|
||||
ret = TRUE;
|
||||
|
||||
ret = WinPrAsn1EncToStream(enc, &s);
|
||||
|
||||
out:
|
||||
WinPrAsn1Encoder_Free(&enc);
|
||||
|
@ -267,6 +267,7 @@ static BOOL freerdp_peer_initialize(freerdp_peer* client)
|
||||
}
|
||||
}
|
||||
|
||||
nego_set_RCG_supported(rdp->nego, settings->RemoteCredentialGuard);
|
||||
if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_INITIAL))
|
||||
return FALSE;
|
||||
|
||||
|
@ -139,6 +139,7 @@ static const size_t bool_list_indices[] = {
|
||||
FreeRDP_RemoteAssistanceMode,
|
||||
FreeRDP_RemoteAssistanceRequestControl,
|
||||
FreeRDP_RemoteConsoleAudio,
|
||||
FreeRDP_RemoteCredentialGuard,
|
||||
FreeRDP_RemoteFxCodec,
|
||||
FreeRDP_RemoteFxImageCodec,
|
||||
FreeRDP_RemoteFxOnly,
|
||||
|
@ -56,6 +56,8 @@ int main(int argc, char** argv)
|
||||
"Select rectangle within monitor to share" },
|
||||
{ "auth", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
|
||||
"Clients must authenticate" },
|
||||
{ "remote-guard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
|
||||
"Remote credential guard" },
|
||||
{ "may-view", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
|
||||
"Clients may view without prompt" },
|
||||
{ "may-interact", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
|
||||
|
@ -303,6 +303,10 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
||||
{
|
||||
server->authentication = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "remote-guard")
|
||||
{
|
||||
settings->RemoteCredentialGuard = arg->Value ? TRUE : FALSE;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "sec")
|
||||
{
|
||||
if (strcmp("rdp", arg->Value) == 0) /* Standard RDP */
|
||||
|
78
winpr/include/winpr/secapi.h
Normal file
78
winpr/include/winpr/secapi.h
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Schannel Security Package
|
||||
*
|
||||
* Copyright 2023 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef WINPR_SECAPI_H_
|
||||
#define WINPR_SECAPI_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _NTDEF_
|
||||
#include <ntsecapi.h>
|
||||
#else
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
typedef enum _KERB_LOGON_SUBMIT_TYPE
|
||||
{
|
||||
KerbInteractiveLogon = 2,
|
||||
KerbSmartCardLogon = 6,
|
||||
KerbWorkstationUnlockLogon = 7,
|
||||
KerbSmartCardUnlockLogon = 8,
|
||||
KerbProxyLogon = 9,
|
||||
KerbTicketLogon = 10,
|
||||
KerbTicketUnlockLogon = 11,
|
||||
KerbS4ULogon = 12,
|
||||
KerbCertificateLogon = 13,
|
||||
KerbCertificateS4ULogon = 14,
|
||||
KerbCertificateUnlockLogon = 15,
|
||||
KerbNoElevationLogon = 83,
|
||||
KerbLuidLogon = 84
|
||||
} KERB_LOGON_SUBMIT_TYPE,
|
||||
*PKERB_LOGON_SUBMIT_TYPE;
|
||||
|
||||
typedef struct _KERB_TICKET_LOGON
|
||||
{
|
||||
KERB_LOGON_SUBMIT_TYPE MessageType;
|
||||
ULONG Flags;
|
||||
ULONG ServiceTicketLength;
|
||||
ULONG TicketGrantingTicketLength;
|
||||
PUCHAR ServiceTicket;
|
||||
PUCHAR TicketGrantingTicket;
|
||||
} KERB_TICKET_LOGON, *PKERB_TICKET_LOGON;
|
||||
|
||||
#define KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET 0x1
|
||||
|
||||
#define MSV1_0_OWF_PASSWORD_LENGTH 16
|
||||
|
||||
typedef struct _MSV1_0_SUPPLEMENTAL_CREDENTIAL
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG Flags;
|
||||
UCHAR LmPassword[MSV1_0_OWF_PASSWORD_LENGTH];
|
||||
UCHAR NtPassword[MSV1_0_OWF_PASSWORD_LENGTH];
|
||||
} MSV1_0_SUPPLEMENTAL_CREDENTIAL, *PMSV1_0_SUPPLEMENTAL_CREDENTIAL;
|
||||
|
||||
#define MSV1_0_CRED_VERSION_REMOTE 0xffff0002
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifndef KERB_LOGON_FLAG_REDIRECTED
|
||||
#define KERB_LOGON_FLAG_REDIRECTED 0x2
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_SECAPI_H_ */
|
Loading…
Reference in New Issue
Block a user