mirror of https://github.com/FreeRDP/FreeRDP
[rdg] implementation of http_extauth_sspi_ntlm
This commit is contained in:
parent
5b09cd57a7
commit
b1583d56c0
|
@ -2964,15 +2964,27 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
|||
else
|
||||
{
|
||||
char* c = strchr(arg->Value, ',');
|
||||
if (c)
|
||||
while (c)
|
||||
{
|
||||
char* next = strchr(c + 1, ',');
|
||||
if (next)
|
||||
*next = '\0';
|
||||
*c++ = '\0';
|
||||
if (!option_equals(c, "no-websockets"))
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
|
||||
if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets,
|
||||
FALSE))
|
||||
if (option_equals(c, "no-websockets"))
|
||||
{
|
||||
if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets,
|
||||
FALSE))
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
}
|
||||
else if (option_equals(c, "extauth-sspi-ntlm"))
|
||||
{
|
||||
if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpExtAuthSspiNtln,
|
||||
TRUE))
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
}
|
||||
else
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
c = next;
|
||||
}
|
||||
|
||||
if (option_equals(arg->Value, "http"))
|
||||
|
|
|
@ -206,8 +206,9 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
|
|||
{ "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
|
||||
"Grab keyboard" },
|
||||
{ "grab-mouse", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab mouse" },
|
||||
{ "gt", COMMAND_LINE_VALUE_REQUIRED, "[rpc|http[,no-websockets]|auto[,no-websockets]]", NULL,
|
||||
NULL, -1, NULL, "Gateway transport type" },
|
||||
{ "gt", COMMAND_LINE_VALUE_REQUIRED,
|
||||
"[rpc|http[,no-websockets][,extauth-sspi-ntlm]|auto[,no-websockets][,extauth-sspi-ntlm]]",
|
||||
NULL, NULL, -1, NULL, "Gateway transport type" },
|
||||
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[[<domain>\\]<user>|<user>[@<domain>]]", NULL, NULL, -1,
|
||||
NULL, "Gateway username" },
|
||||
{ "gat", COMMAND_LINE_VALUE_REQUIRED, "<access token>", NULL, NULL, -1, NULL,
|
||||
|
|
|
@ -772,6 +772,7 @@ typedef struct
|
|||
#define FreeRDP_GatewayAcceptedCert (1998)
|
||||
#define FreeRDP_GatewayAcceptedCertLength (1999)
|
||||
#define FreeRDP_GatewayHttpUseWebsockets (2000)
|
||||
#define FreeRDP_GatewayHttpExtAuthSspiNtln (2001)
|
||||
#define FreeRDP_ProxyType (2015)
|
||||
#define FreeRDP_ProxyHostname (2016)
|
||||
#define FreeRDP_ProxyPort (2017)
|
||||
|
@ -1337,7 +1338,8 @@ struct rdp_settings
|
|||
ALIGN64 char* GatewayAcceptedCert; /* 1998 */
|
||||
ALIGN64 UINT32 GatewayAcceptedCertLength; /* 1999 */
|
||||
ALIGN64 BOOL GatewayHttpUseWebsockets; /* 2000 */
|
||||
UINT64 padding2015[2015 - 2001]; /* 2001 */
|
||||
ALIGN64 BOOL GatewayHttpExtAuthSspiNtln; /* 2001 */
|
||||
UINT64 padding2015[2015 - 2002]; /* 2002 */
|
||||
|
||||
/* Proxy */
|
||||
ALIGN64 UINT32 ProxyType; /* 2015 */
|
||||
|
|
|
@ -222,6 +222,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id)
|
|||
case FreeRDP_GatewayHttpUseWebsockets:
|
||||
return settings->GatewayHttpUseWebsockets;
|
||||
|
||||
case FreeRDP_GatewayHttpExtAuthSspiNtln:
|
||||
return settings->GatewayHttpExtAuthSspiNtln;
|
||||
|
||||
case FreeRDP_GatewayRpcTransport:
|
||||
return settings->GatewayRpcTransport;
|
||||
|
||||
|
@ -829,6 +832,9 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val)
|
|||
case FreeRDP_GatewayHttpUseWebsockets:
|
||||
settings->GatewayHttpUseWebsockets = cnv.c;
|
||||
break;
|
||||
case FreeRDP_GatewayHttpExtAuthSspiNtln:
|
||||
settings->GatewayHttpExtAuthSspiNtln = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_GatewayRpcTransport:
|
||||
settings->GatewayRpcTransport = cnv.c;
|
||||
|
|
|
@ -1000,6 +1000,38 @@ static BOOL rdg_send_handshake(rdpRdg* rdg)
|
|||
return status;
|
||||
}
|
||||
|
||||
static BOOL rdg_send_extauth_sspi(rdpRdg* rdg)
|
||||
{
|
||||
wStream* s;
|
||||
BOOL status;
|
||||
UINT32 packetSize = 8 + 4 + 2;
|
||||
|
||||
WINPR_ASSERT(rdg);
|
||||
|
||||
const SecBuffer* authToken = credssp_auth_get_output_buffer(rdg->auth);
|
||||
if (!authToken)
|
||||
return FALSE;
|
||||
packetSize += authToken->cbBuffer;
|
||||
|
||||
s = Stream_New(NULL, packetSize);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT16(s, PKT_TYPE_EXTENDED_AUTH_MSG); /* Type (2 bytes) */
|
||||
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
|
||||
Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
|
||||
Stream_Write_UINT32(s, ERROR_SUCCESS); /* Error code */
|
||||
Stream_Write_UINT16(s, (UINT16)authToken->cbBuffer);
|
||||
Stream_Write(s, authToken->pvBuffer, authToken->cbBuffer);
|
||||
|
||||
Stream_SealLength(s);
|
||||
status = rdg_write_packet(rdg, s);
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static BOOL rdg_send_tunnel_request(rdpRdg* rdg)
|
||||
{
|
||||
wStream* s;
|
||||
|
@ -1308,6 +1340,9 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (rdg->extAuth == HTTP_EXTENDED_AUTH_SSPI_NTLM)
|
||||
return rdg_send_extauth_sspi(rdg);
|
||||
|
||||
return rdg_send_tunnel_request(rdg);
|
||||
}
|
||||
|
||||
|
@ -1443,6 +1478,53 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
|
|||
return rdg_send_channel_create(rdg);
|
||||
}
|
||||
|
||||
static BOOL rdg_process_extauth_sspi(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
UINT32 errorCode;
|
||||
UINT16 authBlobLen;
|
||||
SecBuffer authToken = { 0 };
|
||||
BYTE* authTokenData = NULL;
|
||||
|
||||
WINPR_ASSERT(rdg);
|
||||
|
||||
Stream_Read_UINT32(s, errorCode);
|
||||
Stream_Read_UINT16(s, authBlobLen);
|
||||
|
||||
if (errorCode != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s] EXTAUTH_SSPI_NTLM failed with error %s [0x%08X]", __FUNCTION__,
|
||||
GetSecurityStatusString(errorCode), errorCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (authBlobLen == 0)
|
||||
{
|
||||
if (credssp_auth_is_complete(rdg->auth))
|
||||
{
|
||||
credssp_auth_free(rdg->auth);
|
||||
rdg->auth = NULL;
|
||||
return rdg_send_tunnel_request(rdg);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
authTokenData = malloc(authBlobLen);
|
||||
Stream_Read(s, authTokenData, authBlobLen);
|
||||
|
||||
authToken.pvBuffer = authTokenData;
|
||||
authToken.cbBuffer = authBlobLen;
|
||||
|
||||
credssp_auth_take_input_buffer(rdg->auth, &authToken);
|
||||
|
||||
if (credssp_auth_authenticate(rdg->auth) < 0)
|
||||
return FALSE;
|
||||
|
||||
if (credssp_auth_have_output_token(rdg->auth))
|
||||
return rdg_send_extauth_sspi(rdg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
|
||||
{
|
||||
UINT16 fieldsPresent;
|
||||
|
@ -1519,6 +1601,14 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
|
|||
case PKT_TYPE_DATA:
|
||||
WLog_ERR(TAG, "[%s] Unexpected packet type DATA", __FUNCTION__);
|
||||
return FALSE;
|
||||
|
||||
case PKT_TYPE_EXTENDED_AUTH_MSG:
|
||||
status = rdg_process_extauth_sspi(rdg, s);
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "[%s] PKG TYPE 0x%x not implemented", __FUNCTION__, type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -1574,7 +1664,7 @@ static BOOL rdg_get_gateway_credentials(rdpContext* context, rdp_auth_reason rea
|
|||
}
|
||||
}
|
||||
|
||||
static BOOL rdg_auth_init(rdpRdg* rdg, rdpTls* tls)
|
||||
static BOOL rdg_auth_init(rdpRdg* rdg, rdpTls* tls, TCHAR* authPkg)
|
||||
{
|
||||
rdpContext* context = rdg->context;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
@ -1585,7 +1675,7 @@ static BOOL rdg_auth_init(rdpRdg* rdg, rdpTls* tls)
|
|||
if (!rdg->auth)
|
||||
return FALSE;
|
||||
|
||||
if (!credssp_auth_init(rdg->auth, AUTH_PKG, tls->Bindings))
|
||||
if (!credssp_auth_init(rdg->auth, authPkg, tls->Bindings))
|
||||
return FALSE;
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon))
|
||||
|
@ -1765,7 +1855,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
|
|||
WINPR_ASSERT(rpcFallback);
|
||||
if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE)
|
||||
{
|
||||
if (!rdg_auth_init(rdg, tls))
|
||||
if (!rdg_auth_init(rdg, tls, AUTH_PKG))
|
||||
return FALSE;
|
||||
|
||||
if (!rdg_send_http_request(rdg, tls, method, TransferEncodingIdentity))
|
||||
|
@ -1880,7 +1970,13 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
|
|||
rdg->transferEncoding.isWebsocketTransport = TRUE;
|
||||
rdg->transferEncoding.context.websocket.state = WebsocketStateOpcodeAndFin;
|
||||
rdg->transferEncoding.context.websocket.responseStreamBuffer = NULL;
|
||||
|
||||
if (rdg->extAuth == HTTP_EXTENDED_AUTH_SSPI_NTLM)
|
||||
{
|
||||
/* create a new auth context for SSPI_NTLM. This must be done after the last
|
||||
* rdg_send_http_request */
|
||||
if (!rdg_auth_init(rdg, tls, NTLM_SSP_NAME))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
|
@ -1904,6 +2000,14 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
|
|||
{
|
||||
if (!rdg_send_http_request(rdg, tls, method, TransferEncodingChunked))
|
||||
return FALSE;
|
||||
|
||||
if (rdg->extAuth == HTTP_EXTENDED_AUTH_SSPI_NTLM)
|
||||
{
|
||||
/* create a new auth context for SSPI_NTLM. This must be done after the last
|
||||
* rdg_send_http_request (RDG_IN_DATA is always after RDG_OUT_DATA) */
|
||||
if (!rdg_auth_init(rdg, tls, NTLM_SSP_NAME))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -2592,7 +2696,8 @@ rdpRdg* rdg_new(rdpContext* context)
|
|||
rdg->state = RDG_CLIENT_STATE_INITIAL;
|
||||
rdg->context = context;
|
||||
rdg->settings = rdg->context->settings;
|
||||
rdg->extAuth = HTTP_EXTENDED_AUTH_NONE;
|
||||
rdg->extAuth = (rdg->settings->GatewayHttpExtAuthSspiNtln ? HTTP_EXTENDED_AUTH_SSPI_NTLM
|
||||
: HTTP_EXTENDED_AUTH_NONE);
|
||||
|
||||
if (rdg->settings->GatewayAccessToken)
|
||||
rdg->extAuth = HTTP_EXTENDED_AUTH_PAA;
|
||||
|
@ -2643,6 +2748,10 @@ rdpRdg* rdg_new(rdpContext* context)
|
|||
if (!http_context_set_rdg_auth_scheme(rdg->http, "PAA"))
|
||||
goto rdg_alloc_error;
|
||||
|
||||
case HTTP_EXTENDED_AUTH_SSPI_NTLM:
|
||||
if (!http_context_set_rdg_auth_scheme(rdg->http, "SSPI_NTLM"))
|
||||
goto rdg_alloc_error;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -601,6 +601,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
|||
!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, TRUE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_GatewayUdpTransport, TRUE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, TRUE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpExtAuthSspiNtln, FALSE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_FastPathInput, TRUE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_FastPathOutput, TRUE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_LongCredentialsSupported, TRUE) ||
|
||||
|
|
Loading…
Reference in New Issue