CredSSP with early user auth (nla_ext) support
This commit is contained in:
parent
535faeb879
commit
b67afecf0f
@ -318,7 +318,11 @@ static BOOL nego_try_connect(rdpNego* nego)
|
||||
break;
|
||||
case PROTOCOL_HYBRID:
|
||||
WLog_DBG(TAG, "nego_security_connect with PROTOCOL_HYBRID");
|
||||
nego->SecurityConnected = transport_connect_nla(nego->transport);
|
||||
nego->SecurityConnected = transport_connect_nla(nego->transport, FALSE);
|
||||
break;
|
||||
case PROTOCOL_HYBRID_EX:
|
||||
WLog_DBG(TAG, "nego_security_connect with PROTOCOL_HYBRID_EX");
|
||||
nego->SecurityConnected = transport_connect_nla(nego->transport, TRUE);
|
||||
break;
|
||||
case PROTOCOL_SSL:
|
||||
WLog_DBG(TAG, "nego_security_connect with PROTOCOL_SSL");
|
||||
|
@ -54,6 +54,12 @@
|
||||
|
||||
#define NLA_AUTH_PKG NEGO_SSP_NAME
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUTHZ_SUCCESS = 0x00000000,
|
||||
AUTHZ_ACCESS_DENIED = 0x00000005,
|
||||
} AUTHZ_RESULT;
|
||||
|
||||
/**
|
||||
* TSRequest ::= SEQUENCE {
|
||||
* version [0] INTEGER,
|
||||
@ -127,6 +133,7 @@ struct rdp_nla
|
||||
char* pkinitArgs;
|
||||
SmartcardCertInfo* smartcardCert;
|
||||
BYTE certSha1[20];
|
||||
BOOL earlyUserAuth;
|
||||
};
|
||||
|
||||
static BOOL nla_send(rdpNla* nla);
|
||||
@ -138,6 +145,13 @@ static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
|
||||
static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
|
||||
static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
|
||||
|
||||
void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
|
||||
{
|
||||
WINPR_ASSERT(nla);
|
||||
WLog_DBG(TAG, "Early User Auth active: %s", nla->earlyUserAuth ? "true" : "false");
|
||||
nla->earlyUserAuth = earlyUserAuth;
|
||||
}
|
||||
|
||||
static void nla_buffer_free(rdpNla* nla)
|
||||
{
|
||||
WINPR_ASSERT(nla);
|
||||
@ -551,6 +565,23 @@ static int nla_client_recv_pub_key_auth(rdpNla* nla)
|
||||
if (!nla_send(nla))
|
||||
return -1;
|
||||
|
||||
if (nla->earlyUserAuth)
|
||||
{
|
||||
transport_set_early_user_auth_mode(nla->transport, TRUE);
|
||||
nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
|
||||
}
|
||||
else
|
||||
nla_set_state(nla, NLA_STATE_AUTH_INFO);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nla_client_recv_early_user_auth(rdpNla* nla)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
|
||||
WINPR_ASSERT(nla);
|
||||
|
||||
transport_set_early_user_auth_mode(nla->transport, FALSE);
|
||||
nla_set_state(nla, NLA_STATE_AUTH_INFO);
|
||||
return 1;
|
||||
}
|
||||
@ -567,6 +598,9 @@ static int nla_client_recv(rdpNla* nla)
|
||||
case NLA_STATE_PUB_KEY_AUTH:
|
||||
return nla_client_recv_pub_key_auth(nla);
|
||||
|
||||
case NLA_STATE_EARLY_USER_AUTH:
|
||||
return nla_client_recv_early_user_auth(nla);
|
||||
|
||||
case NLA_STATE_FINAL:
|
||||
default:
|
||||
WLog_ERR(TAG, "NLA in invalid client receive state %s",
|
||||
@ -1552,63 +1586,80 @@ int nla_recv_pdu(rdpNla* nla, wStream* s)
|
||||
WINPR_ASSERT(nla);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (nla_decode_ts_request(nla, s) < 1)
|
||||
return -1;
|
||||
|
||||
if (nla->errorCode)
|
||||
if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
|
||||
{
|
||||
UINT32 code;
|
||||
|
||||
switch (nla->errorCode)
|
||||
Stream_Read_UINT32(s, code);
|
||||
if (code != AUTHZ_SUCCESS)
|
||||
{
|
||||
case STATUS_PASSWORD_MUST_CHANGE:
|
||||
code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
|
||||
break;
|
||||
|
||||
case STATUS_PASSWORD_EXPIRED:
|
||||
code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_DISABLED:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
|
||||
break;
|
||||
|
||||
case STATUS_LOGON_FAILURE:
|
||||
code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
|
||||
break;
|
||||
|
||||
case STATUS_WRONG_PASSWORD:
|
||||
code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
|
||||
break;
|
||||
|
||||
case STATUS_ACCESS_DENIED:
|
||||
code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_RESTRICTION:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_LOCKED_OUT:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_EXPIRED:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
|
||||
break;
|
||||
|
||||
case STATUS_LOGON_TYPE_NOT_GRANTED:
|
||||
code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: 0x%08" PRIX32 "", nla->errorCode);
|
||||
code = FREERDP_ERROR_AUTHENTICATION_FAILED;
|
||||
break;
|
||||
WLog_DBG(TAG, "Early User Auth active: FAILURE code 0x%08" PRIX32 "", code);
|
||||
code = FREERDP_ERROR_AUTHENTICATION_FAILED;
|
||||
freerdp_set_last_error_log(nla->rdpcontext, code);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
WLog_DBG(TAG, "Early User Auth active: SUCCESS");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nla_decode_ts_request(nla, s) < 1)
|
||||
return -1;
|
||||
|
||||
freerdp_set_last_error_log(nla->rdpcontext, code);
|
||||
return -1;
|
||||
if (nla->errorCode)
|
||||
{
|
||||
UINT32 code;
|
||||
|
||||
switch (nla->errorCode)
|
||||
{
|
||||
case STATUS_PASSWORD_MUST_CHANGE:
|
||||
code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
|
||||
break;
|
||||
|
||||
case STATUS_PASSWORD_EXPIRED:
|
||||
code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_DISABLED:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
|
||||
break;
|
||||
|
||||
case STATUS_LOGON_FAILURE:
|
||||
code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
|
||||
break;
|
||||
|
||||
case STATUS_WRONG_PASSWORD:
|
||||
code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
|
||||
break;
|
||||
|
||||
case STATUS_ACCESS_DENIED:
|
||||
code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_RESTRICTION:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_LOCKED_OUT:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
|
||||
break;
|
||||
|
||||
case STATUS_ACCOUNT_EXPIRED:
|
||||
code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
|
||||
break;
|
||||
|
||||
case STATUS_LOGON_TYPE_NOT_GRANTED:
|
||||
code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: 0x%08" PRIX32 "", nla->errorCode);
|
||||
code = FREERDP_ERROR_AUTHENTICATION_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
freerdp_set_last_error_log(nla->rdpcontext, code);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return nla_client_recv(nla);
|
||||
@ -1658,6 +1709,7 @@ rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
|
||||
nla->sendSeqNum = 0;
|
||||
nla->recvSeqNum = 0;
|
||||
nla->version = 6;
|
||||
nla->earlyUserAuth = FALSE;
|
||||
|
||||
nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
|
||||
if (!nla->identity)
|
||||
@ -1761,6 +1813,8 @@ const char* nla_get_state_str(NLA_STATE state)
|
||||
return "NLA_STATE_AUTH_INFO";
|
||||
case NLA_STATE_POST_NEGO:
|
||||
return "NLA_STATE_POST_NEGO";
|
||||
case NLA_STATE_EARLY_USER_AUTH:
|
||||
return "NLA_STATE_EARLY_USER_AUTH";
|
||||
case NLA_STATE_FINAL:
|
||||
return "NLA_STATE_FINAL";
|
||||
default:
|
||||
|
@ -40,6 +40,7 @@ typedef enum
|
||||
NLA_STATE_INITIAL,
|
||||
NLA_STATE_NEGO_TOKEN,
|
||||
NLA_STATE_PUB_KEY_AUTH,
|
||||
NLA_STATE_EARLY_USER_AUTH,
|
||||
NLA_STATE_AUTH_INFO,
|
||||
NLA_STATE_POST_NEGO,
|
||||
NLA_STATE_FINAL
|
||||
@ -70,5 +71,6 @@ FREERDP_LOCAL BOOL nla_revert_to_self(rdpNla* nla);
|
||||
|
||||
FREERDP_LOCAL rdpNla* nla_new(rdpContext* context, rdpTransport* transport);
|
||||
FREERDP_LOCAL void nla_free(rdpNla* nla);
|
||||
FREERDP_LOCAL void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_NLA_H */
|
||||
|
@ -90,6 +90,7 @@ struct rdp_transport
|
||||
rdpTransportIo io;
|
||||
HANDLE ioEvent;
|
||||
BOOL useIoEvent;
|
||||
BOOL earlyUserAuth;
|
||||
};
|
||||
|
||||
static void transport_ssl_cb(SSL* ssl, int where, int ret)
|
||||
@ -323,7 +324,7 @@ static BOOL transport_default_connect_tls(rdpTransport* transport)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL transport_connect_nla(rdpTransport* transport)
|
||||
BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth)
|
||||
{
|
||||
rdpContext* context = NULL;
|
||||
rdpSettings* settings = NULL;
|
||||
@ -352,6 +353,8 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
||||
if (!rdp->nla)
|
||||
return FALSE;
|
||||
|
||||
nla_set_early_user_auth(rdp->nla, earlyUserAuth);
|
||||
|
||||
transport_set_nla_mode(transport, TRUE);
|
||||
|
||||
if (settings->AuthenticationServiceClass)
|
||||
@ -1028,6 +1031,14 @@ static int transport_default_read_pdu(rdpTransport* transport, wStream* s)
|
||||
Stream_Write_UINT8(s, c);
|
||||
} while (c != '\0');
|
||||
}
|
||||
else if (transport->earlyUserAuth)
|
||||
{
|
||||
if (!Stream_EnsureCapacity(s, 4))
|
||||
return -1;
|
||||
const int rc = transport_read_layer_bytes(transport, s, 4);
|
||||
if (rc != 1)
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read in pdu length */
|
||||
@ -1473,6 +1484,7 @@ static BOOL transport_default_disconnect(rdpTransport* transport)
|
||||
|
||||
transport->frontBio = NULL;
|
||||
transport->layer = TRANSPORT_LAYER_TCP;
|
||||
transport->earlyUserAuth = FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1723,3 +1735,10 @@ BOOL transport_io_callback_set_event(rdpTransport* transport, BOOL set)
|
||||
return ResetEvent(transport->ioEvent);
|
||||
return SetEvent(transport->ioEvent);
|
||||
}
|
||||
|
||||
void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode)
|
||||
{
|
||||
WINPR_ASSERT(transport);
|
||||
transport->earlyUserAuth = EUAMode;
|
||||
WLog_Print(transport->log, WLOG_DEBUG, "Early User Auth Mode: %s", EUAMode ? "on" : "off");
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ FREERDP_LOCAL BOOL transport_attach(rdpTransport* transport, int sockfd);
|
||||
FREERDP_LOCAL BOOL transport_disconnect(rdpTransport* transport);
|
||||
FREERDP_LOCAL BOOL transport_connect_rdp(rdpTransport* transport);
|
||||
FREERDP_LOCAL BOOL transport_connect_tls(rdpTransport* transport);
|
||||
FREERDP_LOCAL BOOL transport_connect_nla(rdpTransport* transport);
|
||||
FREERDP_LOCAL BOOL transport_connect_nla(rdpTransport* transport, BOOL earlyUserAuth);
|
||||
FREERDP_LOCAL BOOL transport_connect_rdstls(rdpTransport* transport);
|
||||
FREERDP_LOCAL BOOL transport_connect_aad(rdpTransport* transport);
|
||||
FREERDP_LOCAL BOOL transport_accept_rdp(rdpTransport* transport);
|
||||
@ -129,4 +129,6 @@ FREERDP_LOCAL int transport_tcp_connect(rdpTransport* transport, const char* hos
|
||||
FREERDP_LOCAL rdpTransport* transport_new(rdpContext* context);
|
||||
FREERDP_LOCAL void transport_free(rdpTransport* transport);
|
||||
|
||||
FREERDP_LOCAL void transport_set_early_user_auth_mode(rdpTransport* transport, BOOL EUAMode);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_TRANSPORT_H */
|
||||
|
@ -54,7 +54,7 @@ static _Unwind_Reason_Code unwind_backtrace_callback(struct _Unwind_Context* con
|
||||
{
|
||||
unwind_info_t* info = &ctx->info[ctx->pos++];
|
||||
info->pc = _Unwind_GetIP(context);
|
||||
info->langSpecificData = _Unwind_GetLanguageSpecificData(context);
|
||||
info->langSpecificData = (void*)_Unwind_GetLanguageSpecificData(context);
|
||||
}
|
||||
|
||||
return _URC_NO_REASON;
|
||||
|
Loading…
Reference in New Issue
Block a user