mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 18:03:30 +08:00
Support using smartcard for gateway authentication
This commit is contained in:
parent
e847f159a6
commit
eb04eb0008
@ -518,7 +518,8 @@ BOOL client_cli_authenticate_ex(freerdp* instance, char** username, char** passw
|
||||
return client_cli_authenticate_raw(instance, reason, username, password, domain);
|
||||
}
|
||||
|
||||
BOOL client_cli_choose_smartcard(SmartcardCertInfo** cert_list, DWORD count, DWORD* choice)
|
||||
BOOL client_cli_choose_smartcard(SmartcardCertInfo** cert_list, DWORD count, DWORD* choice,
|
||||
BOOL gateway)
|
||||
{
|
||||
unsigned long answer;
|
||||
char* p = NULL;
|
||||
@ -545,7 +546,8 @@ BOOL client_cli_choose_smartcard(SmartcardCertInfo** cert_list, DWORD count, DWO
|
||||
{
|
||||
char input[10] = { 0 };
|
||||
|
||||
printf("\nChoose a smartcard to use (0 - %" PRIu32 "): ", count - 1);
|
||||
printf("\nChoose a smartcard to use for %s (0 - %" PRIu32 "): ",
|
||||
gateway ? "gateway authentication" : "logon", count - 1);
|
||||
fflush(stdout);
|
||||
if (!fgets(input, 10, stdin))
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ BOOL freerdp_smartcard_list(const rdpSettings* settings)
|
||||
SmartcardCertInfo** certs = NULL;
|
||||
DWORD i, count;
|
||||
|
||||
if (!smartcard_enumerateCerts(settings, &certs, &count))
|
||||
if (!smartcard_enumerateCerts(settings, &certs, &count, FALSE))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
|
@ -139,7 +139,7 @@ extern "C"
|
||||
char** domain, rdp_auth_reason reason);
|
||||
|
||||
FREERDP_API BOOL client_cli_choose_smartcard(SmartcardCertInfo** cert_list, DWORD count,
|
||||
DWORD* choice);
|
||||
DWORD* choice, BOOL gateway);
|
||||
|
||||
FREERDP_API void
|
||||
freerdp_client_OnChannelConnectedEventHandler(void* context,
|
||||
|
@ -118,7 +118,8 @@ extern "C"
|
||||
char** domain);
|
||||
typedef BOOL (*pAuthenticateEx)(freerdp* instance, char** username, char** password,
|
||||
char** domain, rdp_auth_reason reason);
|
||||
typedef BOOL (*pChooseSmartcard)(SmartcardCertInfo** cert_list, DWORD count, DWORD* choice);
|
||||
typedef BOOL (*pChooseSmartcard)(SmartcardCertInfo** cert_list, DWORD count, DWORD* choice,
|
||||
BOOL gateway);
|
||||
|
||||
/** @brief Callback used if user interaction is required to accept
|
||||
* an unknown certificate.
|
||||
|
@ -43,8 +43,9 @@ typedef struct SmartcardCertInfo_st
|
||||
} SmartcardCertInfo;
|
||||
|
||||
FREERDP_API BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCertInfo*** scCerts,
|
||||
DWORD* retCount);
|
||||
FREERDP_API BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert);
|
||||
DWORD* retCount, BOOL gateway);
|
||||
FREERDP_API BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert,
|
||||
BOOL gateway);
|
||||
FREERDP_API void smartcardCertInfo_Free(SmartcardCertInfo* pscCert);
|
||||
FREERDP_API void smartcardCertList_Free(SmartcardCertInfo** pscCert, DWORD count);
|
||||
|
||||
|
@ -26,10 +26,12 @@
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/winsock.h>
|
||||
#include <winpr/cred.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/error.h>
|
||||
#include <freerdp/utils/ringbuffer.h>
|
||||
#include <freerdp/utils/smartcardlogon.h>
|
||||
|
||||
#include "rdg.h"
|
||||
#include "../credssp_auth.h"
|
||||
@ -193,6 +195,8 @@ struct rdp_rdg
|
||||
UINT16 extAuth;
|
||||
UINT16 reserved2;
|
||||
rdg_http_encoding_context transferEncoding;
|
||||
|
||||
SmartcardCertInfo* smartcard;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -1550,11 +1554,11 @@ DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count)
|
||||
return nCount;
|
||||
}
|
||||
|
||||
static BOOL rdg_get_gateway_credentials(rdpContext* context)
|
||||
static BOOL rdg_get_gateway_credentials(rdpContext* context, rdp_auth_reason reason)
|
||||
{
|
||||
freerdp* instance = context->instance;
|
||||
|
||||
auth_status rc = utils_authenticate_gateway(instance, GW_AUTH_RDG);
|
||||
auth_status rc = utils_authenticate_gateway(instance, reason);
|
||||
switch (rc)
|
||||
{
|
||||
case AUTH_SUCCESS:
|
||||
@ -1581,17 +1585,54 @@ static BOOL rdg_auth_init(rdpRdg* rdg, rdpTls* tls)
|
||||
if (!rdg->auth)
|
||||
return FALSE;
|
||||
|
||||
if (!rdg_get_gateway_credentials(context))
|
||||
return FALSE;
|
||||
|
||||
if (!credssp_auth_init(rdg->auth, AUTH_PKG, tls->Bindings))
|
||||
return FALSE;
|
||||
|
||||
if (sspi_SetAuthIdentityA(&identity, settings->GatewayUsername, settings->GatewayDomain,
|
||||
settings->GatewayPassword) < 0)
|
||||
return FALSE;
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon))
|
||||
{
|
||||
if (!smartcard_getCert(context, &rdg->smartcard, TRUE))
|
||||
return FALSE;
|
||||
|
||||
if (!credssp_auth_setup_client(rdg->auth, "HTTP", settings->GatewayHostname, &identity, NULL))
|
||||
if (!rdg_get_gateway_credentials(context, AUTH_SMARTCARD_PIN))
|
||||
return FALSE;
|
||||
#ifdef _WIN32
|
||||
{
|
||||
CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), { 0 } };
|
||||
LPSTR marshalledCredentials;
|
||||
|
||||
memcpy(certInfo.rgbHashOfCert, rdg->smartcard->sha1Hash,
|
||||
sizeof(certInfo.rgbHashOfCert));
|
||||
|
||||
if (!CredMarshalCredentialA(CertCredential, &certInfo, &marshalledCredentials))
|
||||
{
|
||||
WLog_ERR(TAG, "error marshalling cert credentials");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sspi_SetAuthIdentityA(&identity, marshalledCredentials, NULL,
|
||||
settings->GatewayPassword) < 0)
|
||||
return FALSE;
|
||||
|
||||
CredFree(marshalledCredentials);
|
||||
}
|
||||
#else
|
||||
if (sspi_SetAuthIdentityA(&identity, settings->GatewayUsername, settings->GatewayDomain,
|
||||
settings->GatewayPassword) < 0)
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!rdg_get_gateway_credentials(context, GW_AUTH_RDG))
|
||||
return FALSE;
|
||||
|
||||
if (sspi_SetAuthIdentityA(&identity, settings->GatewayUsername, settings->GatewayDomain,
|
||||
settings->GatewayPassword) < 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!credssp_auth_setup_client(rdg->auth, "HTTP", settings->GatewayHostname, &identity,
|
||||
rdg->smartcard ? rdg->smartcard->pkinitArgs : NULL))
|
||||
{
|
||||
sspi_FreeAuthIdentity(&identity);
|
||||
return FALSE;
|
||||
@ -2626,6 +2667,8 @@ void rdg_free(rdpRdg* rdg)
|
||||
Stream_Free(rdg->transferEncoding.context.websocket.responseStreamBuffer, TRUE);
|
||||
}
|
||||
|
||||
smartcardCertInfo_Free(rdg->smartcard);
|
||||
|
||||
free(rdg);
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
|
||||
|
||||
smartcardCertInfo_Free(nla->smartcardCert);
|
||||
|
||||
if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert))
|
||||
if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to get smartcard certificate for logon");
|
||||
return FALSE;
|
||||
@ -221,24 +221,6 @@ static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->Username && nla->smartcardCert->userHint)
|
||||
{
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_Username, nla->smartcardCert->userHint))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy certificate username");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->Domain && nla->smartcardCert->domainHint)
|
||||
{
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_Domain, nla->smartcardCert->domainHint))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy certificate domain");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->ReaderName && nla->smartcardCert->reader)
|
||||
{
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, nla->smartcardCert->reader, -1, &settings->ReaderName, 0,
|
||||
|
@ -607,14 +607,25 @@ out_error:
|
||||
}
|
||||
|
||||
BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCertInfo*** scCerts,
|
||||
DWORD* retCount)
|
||||
DWORD* retCount, BOOL gateway)
|
||||
{
|
||||
BOOL ret;
|
||||
LPWSTR csp = NULL;
|
||||
const char* ReaderName = freerdp_settings_get_string(settings, FreeRDP_ReaderName);
|
||||
const char* Username = freerdp_settings_get_string(settings, FreeRDP_Username);
|
||||
const char* Domain = freerdp_settings_get_string(settings, FreeRDP_Domain);
|
||||
const char* CspName = freerdp_settings_get_string(settings, FreeRDP_CspName);
|
||||
const char* Username;
|
||||
const char* Domain;
|
||||
|
||||
if (gateway)
|
||||
{
|
||||
Username = freerdp_settings_get_string(settings, FreeRDP_GatewayUsername);
|
||||
Domain = freerdp_settings_get_string(settings, FreeRDP_GatewayDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
Username = freerdp_settings_get_string(settings, FreeRDP_Username);
|
||||
Domain = freerdp_settings_get_string(settings, FreeRDP_Domain);
|
||||
}
|
||||
|
||||
WINPR_ASSERT(settings);
|
||||
WINPR_ASSERT(scCerts);
|
||||
@ -638,19 +649,32 @@ BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCertInfo***
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert)
|
||||
static BOOL set_settings_from_smartcard(rdpSettings* settings, size_t id, const char* value)
|
||||
{
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (!freerdp_settings_get_string(settings, id) && value)
|
||||
if (!freerdp_settings_set_string(settings, id, value))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert, BOOL gateway)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
const freerdp* instance = context->instance;
|
||||
const rdpSettings* settings = context->settings;
|
||||
rdpSettings* settings = context->settings;
|
||||
SmartcardCertInfo** cert_list;
|
||||
DWORD count;
|
||||
size_t username_setting;
|
||||
size_t domain_setting;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (!smartcard_enumerateCerts(settings, &cert_list, &count))
|
||||
if (!smartcard_enumerateCerts(settings, &cert_list, &count, gateway))
|
||||
return FALSE;
|
||||
|
||||
if (count < 1)
|
||||
@ -663,7 +687,8 @@ BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert)
|
||||
{
|
||||
DWORD index;
|
||||
|
||||
if (!instance->ChooseSmartcard || !instance->ChooseSmartcard(cert_list, count, &index))
|
||||
if (!instance->ChooseSmartcard ||
|
||||
!instance->ChooseSmartcard(cert_list, count, &index, gateway))
|
||||
{
|
||||
WLog_ERR(TAG, "more than one suitable smartcard certificate was found");
|
||||
smartcardCertList_Free(cert_list, count);
|
||||
@ -679,6 +704,18 @@ BOOL smartcard_getCert(const rdpContext* context, SmartcardCertInfo** cert)
|
||||
else
|
||||
*cert = cert_list[0];
|
||||
|
||||
username_setting = gateway ? FreeRDP_GatewayUsername : FreeRDP_Username;
|
||||
domain_setting = gateway ? FreeRDP_GatewayDomain : FreeRDP_Domain;
|
||||
|
||||
free(cert_list);
|
||||
|
||||
if (!set_settings_from_smartcard(settings, username_setting, (*cert)->userHint) ||
|
||||
!set_settings_from_smartcard(settings, domain_setting, (*cert)->domainHint))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to set settings from smartcard!");
|
||||
smartcardCertInfo_Free(*cert);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user