Smartcard tls logon fix (#7709)

* Early return authenticate if TLS smartcard logon

* Removed obsolete SmartcardPin and unified AuthenticateEx calls

* Remove password-is-pin from command line

The setting is implied by smartcard-logon and only of interest in
server side code, so the setting is useless

* Rework AUTH_SMARTCARD_PIN

Just prompt for PIN and not user/domain if this is requested.

* Fixed a memory leak in nla.c

* Align credentail prompt

* Handle AUTH_NLA & smartcard, just ask for PIN

* Added assertions, removed duplicate password prompt check

* Move smartcard logon after credential prompt
This commit is contained in:
akallabeth 2022-03-09 09:09:53 +01:00 committed by GitHub
parent ce63397323
commit 704289ffee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 214 additions and 154 deletions

View File

@ -230,43 +230,12 @@ static BOOL freerdp_client_settings_post_process(rdpSettings* settings)
} }
/* deal with the smartcard / smartcard logon stuff */ /* deal with the smartcard / smartcard logon stuff */
if (settings->SmartcardEmulation)
{
/* if no pin is defined on the smartcard emulation use the user password */
if (!settings->SmartcardPin)
{
if (!settings->Password)
{
WLog_ERR(TAG, "No pin or password defined for smartcard emu");
goto out_error;
}
if (!freerdp_settings_set_string(settings, FreeRDP_SmartcardPin, settings->Password))
{
WLog_ERR(TAG, "error when setting smartcard pin to user password");
goto out_error;
}
}
}
if (settings->SmartcardLogon) if (settings->SmartcardLogon)
{ {
settings->TlsSecurity = TRUE; settings->TlsSecurity = TRUE;
settings->RedirectSmartCards = TRUE; settings->RedirectSmartCards = TRUE;
settings->DeviceRedirection = TRUE; settings->DeviceRedirection = TRUE;
freerdp_settings_set_bool(settings, FreeRDP_PasswordIsSmartcardPin, TRUE); freerdp_settings_set_bool(settings, FreeRDP_PasswordIsSmartcardPin, TRUE);
if (!settings->Password && settings->SmartcardEmulation)
{
/* when no user password is provided, in the case of smartcard emulation for smartcard
* logon take the smartcard pin as user password to match PasswordIsSmartcardPin
*/
if (!freerdp_settings_set_string(settings, FreeRDP_Password, settings->SmartcardPin))
{
WLog_ERR(TAG, "error when setting smartcard pin to user password");
goto out_error;
}
}
} }
return TRUE; return TRUE;
@ -423,20 +392,22 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, rdp_auth_reason reaso
char** password, char** domain) char** password, char** domain)
{ {
static const size_t password_size = 512; static const size_t password_size = 512;
const char* auth[] = { "Username: ", "Domain: ", "Password: " }; const char* auth[] = { "Username: ", "Domain: ", "Password: " };
const char* authPin[] = { "Username: ", "Domain: ", "Pin: " }; const char* authPin[] = { "Username: ", "Domain: ", "Smartcard-Pin: " };
const char* gw[] = { "GatewayUsername: ", "GatewayDomain: ", "GatewayPassword: " }; const char* gw[] = { "GatewayUsername: ", "GatewayDomain: ", "GatewayPassword: " };
const char** prompt; const char** prompt;
BOOL pinOnly = FALSE;
switch (reason) switch (reason)
{ {
case AUTH_NLA:
case AUTH_TLS:
case AUTH_RDP:
prompt = auth;
break;
case AUTH_SMARTCARD_PIN: case AUTH_SMARTCARD_PIN:
prompt = authPin; prompt = authPin;
pinOnly = TRUE;
break;
case AUTH_TLS:
case AUTH_RDP:
case AUTH_NLA:
prompt = auth;
break; break;
case GW_AUTH_HTTP: case GW_AUTH_HTTP:
case GW_AUTH_RDG: case GW_AUTH_RDG:
@ -450,7 +421,7 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, rdp_auth_reason reaso
if (!username || !password || !domain) if (!username || !password || !domain)
return FALSE; return FALSE;
if (!*username) if (!*username && !pinOnly)
{ {
size_t username_size = 0; size_t username_size = 0;
printf("%s", prompt[0]); printf("%s", prompt[0]);
@ -468,7 +439,7 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, rdp_auth_reason reaso
} }
} }
if (!*domain) if (!*domain && !pinOnly)
{ {
size_t domain_size = 0; size_t domain_size = 0;
printf("%s", prompt[1]); printf("%s", prompt[1]);

View File

@ -889,10 +889,6 @@ static int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_A
else else
settings->MultitransportFlags = 0; settings->MultitransportFlags = 0;
} }
CommandLineSwitchCase(arg, "password-is-pin")
{
settings->PasswordIsSmartcardPin = enable;
}
CommandLineSwitchEnd(arg) CommandLineSwitchEnd(arg)
return status return status
@ -3396,7 +3392,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
setSmartcardEmulation }, setSmartcardEmulation },
{ "key:", FreeRDP_SmartcardPrivateKey, CMDLINE_SUBOPTION_FILE, { "key:", FreeRDP_SmartcardPrivateKey, CMDLINE_SUBOPTION_FILE,
setSmartcardEmulation }, setSmartcardEmulation },
{ "pin:", FreeRDP_SmartcardPin, CMDLINE_SUBOPTION_STRING, NULL }, { "pin:", FreeRDP_Password, CMDLINE_SUBOPTION_STRING, NULL },
{ "csp:", FreeRDP_CspName, CMDLINE_SUBOPTION_STRING, NULL }, { "csp:", FreeRDP_CspName, CMDLINE_SUBOPTION_STRING, NULL },
{ "reader:", FreeRDP_ReaderName, CMDLINE_SUBOPTION_STRING, NULL }, { "reader:", FreeRDP_ReaderName, CMDLINE_SUBOPTION_STRING, NULL },
{ "card:", FreeRDP_CardName, CMDLINE_SUBOPTION_STRING, NULL }, { "card:", FreeRDP_CardName, CMDLINE_SUBOPTION_STRING, NULL },

View File

@ -276,8 +276,6 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
"Redirect parallel device" }, "Redirect parallel device" },
{ "parent-window", COMMAND_LINE_VALUE_REQUIRED, "<window-id>", NULL, NULL, -1, NULL, { "parent-window", COMMAND_LINE_VALUE_REQUIRED, "<window-id>", NULL, NULL, -1, NULL,
"Parent window id" }, "Parent window id" },
{ "password-is-pin", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL,
"Use smart card authentication with password as smart card PIN" },
{ "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" }, { "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
{ "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" }, { "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" },
{ "pheight", COMMAND_LINE_VALUE_REQUIRED, "<height>", NULL, NULL, -1, NULL, { "pheight", COMMAND_LINE_VALUE_REQUIRED, "<height>", NULL, NULL, -1, NULL,

View File

@ -661,7 +661,6 @@ typedef struct
#define FreeRDP_PromptForCredentials (1283) #define FreeRDP_PromptForCredentials (1283)
#define FreeRDP_SmartcardCertificate (1285) #define FreeRDP_SmartcardCertificate (1285)
#define FreeRDP_SmartcardPrivateKey (1286) #define FreeRDP_SmartcardPrivateKey (1286)
#define FreeRDP_SmartcardPin (1287)
#define FreeRDP_SmartcardEmulation (1288) #define FreeRDP_SmartcardEmulation (1288)
#define FreeRDP_Pkcs11Module (1289) #define FreeRDP_Pkcs11Module (1289)
#define FreeRDP_PkinitAnchors (1290) #define FreeRDP_PkinitAnchors (1290)
@ -1159,7 +1158,7 @@ struct rdp_settings
/* Settings used for smartcard emulation */ /* Settings used for smartcard emulation */
ALIGN64 char* SmartcardCertificate; /* 1285 */ ALIGN64 char* SmartcardCertificate; /* 1285 */
ALIGN64 char* SmartcardPrivateKey; /* 1286 */ ALIGN64 char* SmartcardPrivateKey; /* 1286 */
ALIGN64 char* SmartcardPin; /* 1287 */ UINT64 padding1287[1288 - 1287]; /* 1287 */
ALIGN64 BOOL SmartcardEmulation; /* 1288 */ ALIGN64 BOOL SmartcardEmulation; /* 1288 */
ALIGN64 char* Pkcs11Module; /* 1289 */ ALIGN64 char* Pkcs11Module; /* 1289 */
ALIGN64 char* PkinitAnchors; /* 1290 */ ALIGN64 char* PkinitAnchors; /* 1290 */

View File

@ -2550,9 +2550,6 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
case FreeRDP_SmartcardCertificate: case FreeRDP_SmartcardCertificate:
return settings->SmartcardCertificate; return settings->SmartcardCertificate;
case FreeRDP_SmartcardPin:
return settings->SmartcardPin;
case FreeRDP_SmartcardPrivateKey: case FreeRDP_SmartcardPrivateKey:
return settings->SmartcardPrivateKey; return settings->SmartcardPrivateKey;
@ -2811,9 +2808,6 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
case FreeRDP_SmartcardCertificate: case FreeRDP_SmartcardCertificate:
return settings->SmartcardCertificate; return settings->SmartcardCertificate;
case FreeRDP_SmartcardPin:
return settings->SmartcardPin;
case FreeRDP_SmartcardPrivateKey: case FreeRDP_SmartcardPrivateKey:
return settings->SmartcardPrivateKey; return settings->SmartcardPrivateKey;
@ -3082,9 +3076,6 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
case FreeRDP_SmartcardCertificate: case FreeRDP_SmartcardCertificate:
return update_string(&settings->SmartcardCertificate, cnv.cc, len, cleanup); return update_string(&settings->SmartcardCertificate, cnv.cc, len, cleanup);
case FreeRDP_SmartcardPin:
return update_string(&settings->SmartcardPin, cnv.cc, len, cleanup);
case FreeRDP_SmartcardPrivateKey: case FreeRDP_SmartcardPrivateKey:
return update_string(&settings->SmartcardPrivateKey, cnv.cc, len, cleanup); return update_string(&settings->SmartcardPrivateKey, cnv.cc, len, cleanup);

View File

@ -383,7 +383,6 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_ServerHostname, 7, "FreeRDP_ServerHostname" }, { FreeRDP_ServerHostname, 7, "FreeRDP_ServerHostname" },
{ FreeRDP_ShellWorkingDirectory, 7, "FreeRDP_ShellWorkingDirectory" }, { FreeRDP_ShellWorkingDirectory, 7, "FreeRDP_ShellWorkingDirectory" },
{ FreeRDP_SmartcardCertificate, 7, "FreeRDP_SmartcardCertificate" }, { FreeRDP_SmartcardCertificate, 7, "FreeRDP_SmartcardCertificate" },
{ FreeRDP_SmartcardPin, 7, "FreeRDP_SmartcardPin" },
{ FreeRDP_SmartcardPrivateKey, 7, "FreeRDP_SmartcardPrivateKey" }, { FreeRDP_SmartcardPrivateKey, 7, "FreeRDP_SmartcardPrivateKey" },
{ FreeRDP_TargetNetAddress, 7, "FreeRDP_TargetNetAddress" }, { FreeRDP_TargetNetAddress, 7, "FreeRDP_TargetNetAddress" },
{ FreeRDP_TransportDumpFile, 7, "FreeRDP_TransportDumpFile" }, { FreeRDP_TransportDumpFile, 7, "FreeRDP_TransportDumpFile" },

View File

@ -34,6 +34,7 @@
#include <freerdp/peer.h> #include <freerdp/peer.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/sam.h> #include <winpr/sam.h>
#include <winpr/sspi.h> #include <winpr/sspi.h>
#include <winpr/print.h> #include <winpr/print.h>
@ -171,6 +172,8 @@ static BOOL nla_sec_buffer_alloc(SecBuffer* buffer, size_t size)
sspi_SecBufferFree(buffer); sspi_SecBufferFree(buffer);
if (!sspi_SecBufferAlloc(buffer, size)) if (!sspi_SecBufferAlloc(buffer, size))
return FALSE; return FALSE;
WINPR_ASSERT(buffer);
buffer->BufferType = SECBUFFER_TOKEN; buffer->BufferType = SECBUFFER_TOKEN;
return TRUE; return TRUE;
} }
@ -181,6 +184,8 @@ static BOOL nla_sec_buffer_alloc_from_data(SecBuffer* buffer, const BYTE* data,
BYTE* pb; BYTE* pb;
if (!nla_sec_buffer_alloc(buffer, offset + size)) if (!nla_sec_buffer_alloc(buffer, offset + size))
return FALSE; return FALSE;
WINPR_ASSERT(buffer);
pb = buffer->pvBuffer; pb = buffer->pvBuffer;
memcpy(&pb[offset], data, size); memcpy(&pb[offset], data, size);
return TRUE; return TRUE;
@ -541,10 +546,21 @@ static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
SmartcardCerts* certs = NULL; SmartcardCerts* certs = NULL;
const SmartcardCertInfo* info = NULL; const SmartcardCertInfo* info = NULL;
DWORD count; DWORD count;
rdpSettings* settings = nla->settings; rdpSettings* settings;
SEC_WINPR_KERBEROS_SETTINGS* kerbSettings = &nla->kerberosSettings; SEC_WINPR_KERBEROS_SETTINGS* kerbSettings;
BOOL ret = FALSE; BOOL ret = FALSE;
WINPR_ASSERT(nla);
settings = nla->settings;
WINPR_ASSERT(settings);
if (!settings->SmartcardLogon)
return TRUE;
kerbSettings = &nla->kerberosSettings;
WINPR_ASSERT(kerbSettings);
if (!settings->CspName) if (!settings->CspName)
{ {
if (!freerdp_settings_set_string(settings, FreeRDP_CspName, MS_SCARD_PROV_A)) if (!freerdp_settings_set_string(settings, FreeRDP_CspName, MS_SCARD_PROV_A))
@ -636,33 +652,6 @@ static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
} }
setup_pin: setup_pin:
if (!settings->SmartcardPin)
{
if (settings->SmartcardEmulation)
{
if (!freerdp_settings_set_string(settings, FreeRDP_SmartcardPin, ""))
{
WLog_ERR(TAG, "error setting pin");
return FALSE;
}
}
else
{
freerdp* instance = nla->instance;
if (!instance->AuthenticateEx)
{
WLog_ERR(TAG, "no pin configured and no instance->AuthenticateEx callback");
return TRUE;
}
if (!instance->AuthenticateEx(instance, &settings->Username, &settings->SmartcardPin,
&settings->Domain, AUTH_SMARTCARD_PIN))
{
WLog_ERR(TAG, "no pin code entered");
return TRUE;
}
}
}
ret = TRUE; ret = TRUE;
out: out:
@ -676,64 +665,16 @@ static BOOL nla_client_setup_identity(rdpNla* nla)
WINPR_SAM* sam; WINPR_SAM* sam;
WINPR_SAM_ENTRY* entry; WINPR_SAM_ENTRY* entry;
BOOL PromptPassword = FALSE; BOOL PromptPassword = FALSE;
rdpSettings* settings = nla->settings; rdpSettings* settings;
freerdp* instance = nla->instance; freerdp* instance;
if (settings->SmartcardLogon) WINPR_ASSERT(nla);
{
#ifdef _WIN32
{
SEC_WINNT_AUTH_IDENTITY_EXA* identityEx;
CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), { 0 } };
LPSTR marshalledCredentials;
identityEx = &nla->identityEx; settings = nla->settings;
memcpy(certInfo.rgbHashOfCert, nla->kerberosSettings.certSha1, WINPR_ASSERT(settings);
sizeof(certInfo.rgbHashOfCert));
if (!CredMarshalCredentialA(CertCredential, &certInfo, &marshalledCredentials)) instance = nla->instance;
{ WINPR_ASSERT(instance);
WLog_ERR(TAG, "error marshalling cert credentials");
return FALSE;
}
identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
identityEx->Length = sizeof(*identityEx);
identityEx->User = (BYTE*)marshalledCredentials;
identityEx->UserLength = strlen(marshalledCredentials);
if (!(identityEx->Password = (BYTE*)_strdup(settings->SmartcardPin)))
return FALSE;
identityEx->PasswordLength = strlen(settings->SmartcardPin);
identityEx->Domain = NULL;
identityEx->DomainLength = 0;
identityEx->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
identityEx->PackageList = NULL;
identityEx->PackageListLength = 0;
nla->identityPtr = identityEx;
}
#else
{
SEC_WINNT_AUTH_IDENTITY_EXA* identityEx = &nla->identityWinPr.identityEx;
identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
identityEx->Length = sizeof(nla->identityWinPr);
identityEx->User = (BYTE*)settings->Username;
identityEx->UserLength = strlen(settings->Username);
identityEx->Domain = (BYTE*)settings->Domain;
identityEx->DomainLength = strlen(settings->Domain);
identityEx->Password = (BYTE*)settings->SmartcardPin;
identityEx->PasswordLength = strlen(settings->SmartcardPin);
identityEx->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
identityEx->PackageList = NULL;
identityEx->PackageListLength = 0;
nla->identityPtr = &nla->identityWinPr;
} /* smartcard logon */
#endif /* _WIN32 */
return TRUE;
}
/* */ /* */
if ((utils_str_is_empty(settings->Username) || if ((utils_str_is_empty(settings->Username) ||
@ -795,6 +736,61 @@ static BOOL nla_client_setup_identity(rdpNla* nla)
nla_identity_free(nla->identity); nla_identity_free(nla->identity);
nla->identity = NULL; nla->identity = NULL;
} }
else if (settings->SmartcardLogon)
{
#ifdef _WIN32
{
SEC_WINNT_AUTH_IDENTITY_EXA* identityEx;
CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), { 0 } };
LPSTR marshalledCredentials;
identityEx = &nla->identityEx;
memcpy(certInfo.rgbHashOfCert, nla->kerberosSettings.certSha1,
sizeof(certInfo.rgbHashOfCert));
if (!CredMarshalCredentialA(CertCredential, &certInfo, &marshalledCredentials))
{
WLog_ERR(TAG, "error marshalling cert credentials");
return FALSE;
}
identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
identityEx->Length = sizeof(*identityEx);
identityEx->User = (BYTE*)marshalledCredentials;
identityEx->UserLength = strlen(marshalledCredentials);
if (!(identityEx->Password = (BYTE*)_strdup(settings->Password)))
return FALSE;
identityEx->PasswordLength = strlen(settings->Password);
identityEx->Domain = NULL;
identityEx->DomainLength = 0;
identityEx->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
identityEx->PackageList = NULL;
identityEx->PackageListLength = 0;
nla->identityPtr = identityEx;
}
#else
{
SEC_WINNT_AUTH_IDENTITY_EXA* identityEx = &nla->identityWinPr.identityEx;
identityEx->Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
identityEx->Length = sizeof(nla->identityWinPr);
identityEx->User = (BYTE*)settings->Username;
identityEx->UserLength = strlen(settings->Username);
identityEx->Domain = (BYTE*)settings->Domain;
identityEx->DomainLength = strlen(settings->Domain);
identityEx->Password = (BYTE*)settings->Password;
identityEx->PasswordLength = strlen(settings->Password);
identityEx->Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
identityEx->PackageList = NULL;
identityEx->PackageListLength = 0;
nla->identityPtr = &nla->identityWinPr;
} /* smartcard logon */
#endif /* _WIN32 */
return TRUE;
}
else else
{ {
BOOL usePassword = TRUE; BOOL usePassword = TRUE;
@ -857,6 +853,11 @@ static BOOL parseKerberosDeltat(const char* value, INT32* dest, const char* mess
{ {
INT32 v; INT32 v;
const char* ptr; const char* ptr;
WINPR_ASSERT(value);
WINPR_ASSERT(dest);
WINPR_ASSERT(message);
/* determine the format : /* determine the format :
* h:m[:s] (3:00:02) deltat in hours/minutes * h:m[:s] (3:00:02) deltat in hours/minutes
* <n>d<n>h<n>m<n>s 1d4h deltat in day/hours/minutes/seconds * <n>d<n>h<n>m<n>s 1d4h deltat in day/hours/minutes/seconds
@ -963,8 +964,16 @@ static BOOL parseKerberosDeltat(const char* value, INT32* dest, const char* mess
static BOOL nla_setup_kerberos(rdpNla* nla) static BOOL nla_setup_kerberos(rdpNla* nla)
{ {
SEC_WINPR_KERBEROS_SETTINGS* kerbSettings = &nla->kerberosSettings; SEC_WINPR_KERBEROS_SETTINGS* kerbSettings;
rdpSettings* settings = nla->settings; rdpSettings* settings;
WINPR_ASSERT(nla);
settings = nla->settings;
WINPR_ASSERT(settings);
kerbSettings = &nla->kerberosSettings;
WINPR_ASSERT(kerbSettings);
if (settings->KerberosLifeTime && if (settings->KerberosLifeTime &&
!parseKerberosDeltat(settings->KerberosLifeTime, &kerbSettings->lifeTime, "lifetime")) !parseKerberosDeltat(settings->KerberosLifeTime, &kerbSettings->lifeTime, "lifetime"))
@ -1012,7 +1021,12 @@ static int nla_client_init(rdpNla* nla)
char* spn; char* spn;
size_t length; size_t length;
rdpTls* tls = NULL; rdpTls* tls = NULL;
rdpSettings* settings = nla->settings; rdpSettings* settings;
WINPR_ASSERT(nla);
settings = nla->settings;
WINPR_ASSERT(settings);
nla_set_state(nla, NLA_STATE_INITIAL); nla_set_state(nla, NLA_STATE_INITIAL);
@ -1022,7 +1036,7 @@ static int nla_client_init(rdpNla* nla)
if (!nla_setup_kerberos(nla)) if (!nla_setup_kerberos(nla))
return -1; return -1;
if (settings->SmartcardLogon && !nla_adjust_settings_from_smartcard(nla)) if (!nla_adjust_settings_from_smartcard(nla))
return -1; return -1;
if (!nla_client_setup_identity(nla)) if (!nla_client_setup_identity(nla))
@ -1124,6 +1138,9 @@ int nla_client_begin(rdpNla* nla)
int rc = -1; int rc = -1;
SecBuffer outputBuffer = { 0 }; SecBuffer outputBuffer = { 0 };
SecBufferDesc outputBufferDesc = { 0 }; SecBufferDesc outputBufferDesc = { 0 };
WINPR_ASSERT(nla);
if (nla_client_init(nla) < 1) if (nla_client_init(nla) < 1)
goto fail; goto fail;
@ -1183,6 +1200,8 @@ static int nla_client_recv_nego_token(rdpNla* nla)
SecBufferDesc inputBufferDesc = { 0 }; SecBufferDesc inputBufferDesc = { 0 };
SecBufferDesc outputBufferDesc = { 0 }; SecBufferDesc outputBufferDesc = { 0 };
WINPR_ASSERT(nla);
inputBufferDesc.ulVersion = SECBUFFER_VERSION; inputBufferDesc.ulVersion = SECBUFFER_VERSION;
inputBufferDesc.cBuffers = 1; inputBufferDesc.cBuffers = 1;
inputBufferDesc.pBuffers = &inputBuffer; inputBufferDesc.pBuffers = &inputBuffer;
@ -1250,6 +1269,8 @@ fail:
static int nla_client_recv_pub_key_auth(rdpNla* nla) static int nla_client_recv_pub_key_auth(rdpNla* nla)
{ {
WINPR_ASSERT(nla);
/* Verify Server Public Key Echo */ /* Verify Server Public Key Echo */
if (nla->peerVersion < 5) if (nla->peerVersion < 5)
nla->status = nla_decrypt_public_key_echo(nla); nla->status = nla_decrypt_public_key_echo(nla);
@ -1299,6 +1320,8 @@ static int nla_client_recv_pub_key_auth(rdpNla* nla)
static int nla_client_recv(rdpNla* nla) static int nla_client_recv(rdpNla* nla)
{ {
WINPR_ASSERT(nla);
switch (nla_get_state(nla)) switch (nla_get_state(nla))
{ {
case NLA_STATE_NEGO_TOKEN: case NLA_STATE_NEGO_TOKEN:
@ -1320,6 +1343,9 @@ static int nla_client_authenticate(rdpNla* nla)
int rc = -1; int rc = -1;
wStream* s; wStream* s;
int status; int status;
WINPR_ASSERT(nla);
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
@ -1361,7 +1387,12 @@ fail:
static int nla_server_init(rdpNla* nla) static int nla_server_init(rdpNla* nla)
{ {
rdpTls* tls = transport_get_tls(nla->transport); rdpTls* tls;
WINPR_ASSERT(nla);
tls = transport_get_tls(nla->transport);
WINPR_ASSERT(tls);
if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, tls->PublicKey, 0, tls->PublicKeyLength)) if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, tls->PublicKey, 0, tls->PublicKeyLength))
{ {
@ -1438,6 +1469,9 @@ static wStream* nla_server_recv_stream(rdpNla* nla)
{ {
wStream* s = NULL; wStream* s = NULL;
int status = -1; int status = -1;
WINPR_ASSERT(nla);
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
@ -1465,6 +1499,9 @@ fail:
static int nla_server_authenticate(rdpNla* nla) static int nla_server_authenticate(rdpNla* nla)
{ {
int res = -1; int res = -1;
WINPR_ASSERT(nla);
if (nla_server_init(nla) < 1) if (nla_server_init(nla) < 1)
goto fail_auth; goto fail_auth;
@ -1719,6 +1756,8 @@ fail_auth:
int nla_authenticate(rdpNla* nla) int nla_authenticate(rdpNla* nla)
{ {
WINPR_ASSERT(nla);
if (nla->server) if (nla->server)
return nla_server_authenticate(nla); return nla_server_authenticate(nla);
else else
@ -1729,6 +1768,8 @@ static void ap_integer_increment_le(BYTE* number, size_t size)
{ {
size_t index; size_t index;
WINPR_ASSERT(number || (size == 0));
for (index = 0; index < size; index++) for (index = 0; index < size; index++)
{ {
if (number[index] < 0xFF) if (number[index] < 0xFF)
@ -1748,6 +1789,8 @@ static void ap_integer_decrement_le(BYTE* number, size_t size)
{ {
size_t index; size_t index;
WINPR_ASSERT(number || (size == 0));
for (index = 0; index < size; index++) for (index = 0; index < size; index++)
{ {
if (number[index] > 0) if (number[index] > 0)
@ -1767,6 +1810,8 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
{ {
SECURITY_STATUS status; SECURITY_STATUS status;
WINPR_ASSERT(nla);
if (!nla_sec_buffer_alloc_from_buffer(&nla->pubKeyAuth, &nla->PublicKey, if (!nla_sec_buffer_alloc_from_buffer(&nla->pubKeyAuth, &nla->PublicKey,
nla->ContextSizes.cbSecurityTrailer)) nla->ContextSizes.cbSecurityTrailer))
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
@ -1790,6 +1835,9 @@ SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla)
SECURITY_STATUS status = SEC_E_INTERNAL_ERROR; SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
WINPR_DIGEST_CTX* sha256 = NULL; WINPR_DIGEST_CTX* sha256 = NULL;
BYTE* hash; BYTE* hash;
WINPR_ASSERT(nla);
const ULONG auth_data_length = const ULONG auth_data_length =
(nla->ContextSizes.cbSecurityTrailer + WINPR_SHA256_DIGEST_LENGTH); (nla->ContextSizes.cbSecurityTrailer + WINPR_SHA256_DIGEST_LENGTH);
const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic; const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
@ -1893,6 +1941,9 @@ SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla)
WINPR_DIGEST_CTX* sha256 = NULL; WINPR_DIGEST_CTX* sha256 = NULL;
BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH]; BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH];
SECURITY_STATUS status = SEC_E_INVALID_TOKEN; SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
WINPR_ASSERT(nla);
const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic; const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
const BYTE* decryptedHash; const BYTE* decryptedHash;
const size_t hashSize = const size_t hashSize =
@ -1954,6 +2005,9 @@ BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
{ {
size_t length; size_t length;
WINPR_ASSERT(nla);
WINPR_ASSERT(s);
if (!nla->identity) if (!nla->identity)
{ {
WLog_ERR(TAG, "nla->identity is NULL!"); WLog_ERR(TAG, "nla->identity is NULL!");
@ -2048,6 +2102,7 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data, size_t offset)
size_t ts_password_creds_length = 0; size_t ts_password_creds_length = 0;
BOOL ret = FALSE; BOOL ret = FALSE;
WINPR_ASSERT(nla);
if (!data) if (!data)
return FALSE; return FALSE;
@ -2087,8 +2142,10 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
wStream* s; wStream* s;
size_t length; size_t length;
BOOL ret = FALSE; BOOL ret = FALSE;
TSCredentials_t cr = { 0 }; TSCredentials_t cr = { 0 };
WINPR_ASSERT(nla);
rdpSettings* settings = nla->settings; rdpSettings* settings = nla->settings;
if (settings->SmartcardLogon) if (settings->SmartcardLogon)
@ -2096,7 +2153,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
TSSmartCardCreds_t smartcardCreds = { 0 }; TSSmartCardCreds_t smartcardCreds = { 0 };
TSCspDataDetail_t cspData = { 0 }; TSCspDataDetail_t cspData = { 0 };
smartcardCreds.pin = settings->SmartcardPin ? settings->SmartcardPin : ""; smartcardCreds.pin = settings->Password ? settings->Password : "";
/*smartcardCreds.userHint = settings->UserHint; /*smartcardCreds.userHint = settings->UserHint;
smartcardCreds.domainHint = settings->DomainHint;*/ smartcardCreds.domainHint = settings->DomainHint;*/
@ -2167,6 +2224,8 @@ static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
{ {
SECURITY_STATUS status; SECURITY_STATUS status;
WINPR_ASSERT(nla);
if (!nla_encode_ts_credentials(nla)) if (!nla_encode_ts_credentials(nla))
return SEC_E_INSUFFICIENT_MEMORY; return SEC_E_INSUFFICIENT_MEMORY;
@ -2185,6 +2244,8 @@ static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
{ {
SECURITY_STATUS status; SECURITY_STATUS status;
WINPR_ASSERT(nla);
if (nla->authInfo.cbBuffer < 1) if (nla->authInfo.cbBuffer < 1)
{ {
WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer"); WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
@ -2210,6 +2271,8 @@ static size_t nla_sizeof_nego_token(size_t length)
static size_t nla_sizeof_nego_tokens(const SecBuffer* buffer) static size_t nla_sizeof_nego_tokens(const SecBuffer* buffer)
{ {
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer; size_t length = buffer->cbBuffer;
if (length == 0) if (length == 0)
return 0; return 0;
@ -2222,6 +2285,8 @@ static size_t nla_sizeof_nego_tokens(const SecBuffer* buffer)
static size_t nla_sizeof_pub_key_auth(const SecBuffer* buffer) static size_t nla_sizeof_pub_key_auth(const SecBuffer* buffer)
{ {
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer; size_t length = buffer->cbBuffer;
if (length == 0) if (length == 0)
return 0; return 0;
@ -2232,6 +2297,8 @@ static size_t nla_sizeof_pub_key_auth(const SecBuffer* buffer)
static size_t nla_sizeof_auth_info(const SecBuffer* buffer) static size_t nla_sizeof_auth_info(const SecBuffer* buffer)
{ {
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer; size_t length = buffer->cbBuffer;
if (length == 0) if (length == 0)
return 0; return 0;
@ -2242,6 +2309,8 @@ static size_t nla_sizeof_auth_info(const SecBuffer* buffer)
static size_t nla_sizeof_client_nonce(const SecBuffer* buffer) static size_t nla_sizeof_client_nonce(const SecBuffer* buffer)
{ {
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer; size_t length = buffer->cbBuffer;
if (length == 0) if (length == 0)
return 0; return 0;
@ -2261,6 +2330,8 @@ static BOOL nla_client_write_nego_token(wStream* s, const SecBuffer* negoToken)
{ {
const size_t nego_tokens_length = nla_sizeof_nego_tokens(negoToken); const size_t nego_tokens_length = nla_sizeof_nego_tokens(negoToken);
WINPR_ASSERT(s);
if (Stream_GetRemainingCapacity(s) < nego_tokens_length) if (Stream_GetRemainingCapacity(s) < nego_tokens_length)
return FALSE; return FALSE;
@ -2301,6 +2372,9 @@ BOOL nla_send(rdpNla* nla)
size_t ts_request_length; size_t ts_request_length;
size_t error_code_context_length = 0; size_t error_code_context_length = 0;
size_t error_code_length = 0; size_t error_code_length = 0;
WINPR_ASSERT(nla);
const size_t nego_tokens_length = nla_sizeof_nego_tokens(&nla->negoToken); const size_t nego_tokens_length = nla_sizeof_nego_tokens(&nla->negoToken);
const size_t pub_key_auth_length = nla_sizeof_pub_key_auth(&nla->pubKeyAuth); const size_t pub_key_auth_length = nla_sizeof_pub_key_auth(&nla->pubKeyAuth);
const size_t auth_info_length = nla_sizeof_auth_info(&nla->authInfo); const size_t auth_info_length = nla_sizeof_auth_info(&nla->authInfo);
@ -2389,6 +2463,9 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
size_t length; size_t length;
UINT32 version = 0; UINT32 version = 0;
WINPR_ASSERT(nla);
WINPR_ASSERT(s);
WLog_DBG(TAG, "<<----- receiving..."); WLog_DBG(TAG, "<<----- receiving...");
/* TSRequest */ /* TSRequest */
@ -2471,6 +2548,9 @@ fail:
int nla_recv_pdu(rdpNla* nla, wStream* s) int nla_recv_pdu(rdpNla* nla, wStream* s)
{ {
WINPR_ASSERT(nla);
WINPR_ASSERT(s);
if (nla_decode_ts_request(nla, s) < 1) if (nla_decode_ts_request(nla, s) < 1)
return -1; return -1;
@ -2536,7 +2616,11 @@ int nla_recv_pdu(rdpNla* nla, wStream* s)
int nla_server_recv(rdpNla* nla) int nla_server_recv(rdpNla* nla)
{ {
int status = -1; int status = -1;
wStream* s = nla_server_recv_stream(nla); wStream* s;
WINPR_ASSERT(nla);
s = nla_server_recv_stream(nla);
if (!s) if (!s)
goto fail; goto fail;
status = nla_decode_ts_request(nla, s); status = nla_decode_ts_request(nla, s);
@ -2548,6 +2632,7 @@ fail:
void nla_buffer_free(rdpNla* nla) void nla_buffer_free(rdpNla* nla)
{ {
WINPR_ASSERT(nla);
sspi_SecBufferFree(&nla->negoToken); sspi_SecBufferFree(&nla->negoToken);
sspi_SecBufferFree(&nla->pubKeyAuth); sspi_SecBufferFree(&nla->pubKeyAuth);
sspi_SecBufferFree(&nla->authInfo); sspi_SecBufferFree(&nla->authInfo);

View File

@ -392,7 +392,6 @@ static const size_t string_list_indices[] = {
FreeRDP_ServerHostname, FreeRDP_ServerHostname,
FreeRDP_ShellWorkingDirectory, FreeRDP_ShellWorkingDirectory,
FreeRDP_SmartcardCertificate, FreeRDP_SmartcardCertificate,
FreeRDP_SmartcardPin,
FreeRDP_SmartcardPrivateKey, FreeRDP_SmartcardPrivateKey,
FreeRDP_TargetNetAddress, FreeRDP_TargetNetAddress,
FreeRDP_TransportDumpFile, FreeRDP_TransportDumpFile,

View File

@ -107,6 +107,28 @@ auth_status utils_authenticate(freerdp* instance, rdp_auth_reason reason, BOOL o
if (!prompt) if (!prompt)
return AUTH_SKIP; return AUTH_SKIP;
switch (reason)
{
case AUTH_RDP:
case AUTH_TLS:
if (instance->settings->SmartcardLogon)
{
if (!utils_str_is_empty(settings->Password))
{
WLog_INFO(TAG, "Authentication via smartcard");
return AUTH_SUCCESS;
}
reason = AUTH_SMARTCARD_PIN;
}
break;
case AUTH_NLA:
if (instance->settings->SmartcardLogon)
reason = AUTH_SMARTCARD_PIN;
break;
default:
break;
}
/* If no callback is specified still continue connection */ /* If no callback is specified still continue connection */
if (!instance->Authenticate && !instance->AuthenticateEx) if (!instance->Authenticate && !instance->AuthenticateEx)
return AUTH_NO_CREDENTIALS; return AUTH_NO_CREDENTIALS;

View File

@ -304,7 +304,7 @@ static SCardHandle* scard_handle_new(SmartcardEmulationContext* smartcard, SCARD
const char* key = const char* key =
freerdp_settings_get_string(smartcard->settings, FreeRDP_SmartcardPrivateKey); freerdp_settings_get_string(smartcard->settings, FreeRDP_SmartcardPrivateKey);
const char* pin = freerdp_settings_get_string(smartcard->settings, FreeRDP_SmartcardPin); const char* pin = freerdp_settings_get_string(smartcard->settings, FreeRDP_Password);
if (!vgids_init(hdl->vgids, pem, key, pin)) if (!vgids_init(hdl->vgids, pem, key, pin))
goto fail; goto fail;
@ -2690,7 +2690,7 @@ BOOL Emulate_IsConfigured(SmartcardEmulationContext* context)
pem = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardCertificate); pem = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardCertificate);
key = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardPrivateKey); key = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardPrivateKey);
pin = freerdp_settings_get_string(context->settings, FreeRDP_SmartcardPin); pin = freerdp_settings_get_string(context->settings, FreeRDP_Password);
/* Cache result only, if no initialization arguments changed. */ /* Cache result only, if no initialization arguments changed. */
if ((context->pem == pem) && (context->key == key) && (context->pin == pin)) if ((context->pem == pem) && (context->key == key) && (context->pin == pin))