mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
Enable smartcard NLA logon
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include <freerdp/client.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
#include <freerdp/locale/keyboard.h>
|
||||
#include <freerdp/utils/smartcard_cli.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
@@ -702,15 +703,14 @@ int main(int argc, char* argv[])
|
||||
status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE);
|
||||
if (status)
|
||||
{
|
||||
BOOL list;
|
||||
|
||||
rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
|
||||
|
||||
list = settings->ListMonitors;
|
||||
|
||||
if (list)
|
||||
if (settings->ListMonitors)
|
||||
wlf_list_monitors(wlc);
|
||||
|
||||
if (settings->ListSmartcards)
|
||||
freerdp_smartcard_list(settings);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <freerdp/client/cmdline.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/utils/smartcard_cli.h>
|
||||
|
||||
#include "../resource/resource.h"
|
||||
|
||||
@@ -103,10 +104,13 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
goto out;
|
||||
|
||||
status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE);
|
||||
|
||||
if (status)
|
||||
{
|
||||
ret = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
|
||||
|
||||
if (settings->ListSmartcards)
|
||||
freerdp_smartcard_list(settings);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <freerdp/streamdump.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/client/cmdline.h>
|
||||
#include <freerdp/utils/smartcard_cli.h>
|
||||
|
||||
#include "../xf_client.h"
|
||||
#include "../xfreerdp.h"
|
||||
@@ -59,15 +60,14 @@ int main(int argc, char* argv[])
|
||||
status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE);
|
||||
if (status)
|
||||
{
|
||||
BOOL list;
|
||||
|
||||
rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
|
||||
|
||||
list = settings->ListMonitors;
|
||||
|
||||
if (list)
|
||||
if (settings->ListMonitors)
|
||||
xf_list_monitors(xfc);
|
||||
|
||||
if (settings->ListSmartcards)
|
||||
freerdp_smartcard_list(settings);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +253,6 @@ static BOOL freerdp_client_settings_post_process(rdpSettings* settings)
|
||||
|
||||
if (settings->SmartcardLogon)
|
||||
{
|
||||
settings->NlaSecurity = FALSE; /* for now */
|
||||
settings->TlsSecurity = TRUE;
|
||||
settings->RedirectSmartCards = TRUE;
|
||||
settings->DeviceRedirection = TRUE;
|
||||
@@ -427,6 +426,7 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, rdp_auth_reason reaso
|
||||
{
|
||||
static const size_t password_size = 512;
|
||||
const char* auth[] = { "Username: ", "Domain: ", "Password: " };
|
||||
const char* authPin[] = { "Username: ", "Domain: ", "Pin: " };
|
||||
const char* gw[] = { "GatewayUsername: ", "GatewayDomain: ", "GatewayPassword: " };
|
||||
const char** prompt;
|
||||
|
||||
@@ -437,6 +437,9 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, rdp_auth_reason reaso
|
||||
case AUTH_RDP:
|
||||
prompt = auth;
|
||||
break;
|
||||
case AUTH_SMARTCARD_PIN:
|
||||
prompt = authPin;
|
||||
break;
|
||||
case GW_AUTH_HTTP:
|
||||
case GW_AUTH_RDG:
|
||||
case GW_AUTH_RPC:
|
||||
@@ -516,21 +519,14 @@ BOOL client_cli_authenticate_ex(freerdp* instance, char** username, char** passw
|
||||
WINPR_ASSERT(password);
|
||||
WINPR_ASSERT(domain);
|
||||
|
||||
if (instance->settings->SmartcardLogon)
|
||||
{
|
||||
WLog_INFO(TAG, "Authentication via smartcard");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch (reason)
|
||||
{
|
||||
case AUTH_NLA:
|
||||
break;
|
||||
|
||||
case AUTH_TLS:
|
||||
if ((*username) && (*password))
|
||||
return TRUE;
|
||||
break;
|
||||
case AUTH_RDP:
|
||||
case AUTH_SMARTCARD_PIN: /* in this case password is pin code */
|
||||
if ((*username) && (*password))
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
@@ -24,12 +24,13 @@
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/ncrypt.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/settings.h>
|
||||
@@ -479,6 +480,22 @@ BOOL freerdp_client_print_command_line_help_ex(int argc, char** argv,
|
||||
printf("\n");
|
||||
printf("Drive Redirection: /drive:home,/home/user\n");
|
||||
printf("Smartcard Redirection: /smartcard:<device>\n");
|
||||
printf("Smartcard logon with rdp only: /smartcard-logon [/sec:rdp]\n");
|
||||
printf("Smartcard logon with Kerberos authentication: /smartcard-logon /sec:nla\n");
|
||||
printf("Those options are only accepted with /smartcard-logon:\n");
|
||||
printf(" PIN code: /pin:<PIN code>\n");
|
||||
printf(" PKCS11 module to load: /pkcs11-module:<module>\n");
|
||||
printf(" PKINIT anchors: /pkinit-anchors:<pkinit_anchors>\n");
|
||||
printf(" Kerberos Ticket start time: /start-time:<delay to issue ticket>\n");
|
||||
printf(" Kerberos Ticket lifetime: /lifetime:<ticket lifetime>\n");
|
||||
printf(" Kerberos Ticket renewable lifetime: /renewable-lifetime:<ticket renewable "
|
||||
"lifetime>\n");
|
||||
/* See also http://web.mit.edu/kerberos/krb5-latest/doc/basic/date_format.html */
|
||||
printf(" The delay and lifetime have the following syntax: <integer>[s|m|h|d] (for seconds, "
|
||||
" minutes, hours and days)\n");
|
||||
printf(" CSP Name: /csp:<csp name>\n");
|
||||
printf(" Card Name: /card:<card name>\n");
|
||||
|
||||
printf("Serial Port Redirection: /serial:<name>,<device>,[SerCx2|SerCx|Serial],[permissive]\n");
|
||||
printf("Serial Port Redirection: /serial:COM1,/dev/ttyS0\n");
|
||||
printf("Parallel Port Redirection: /parallel:<name>,<device>\n");
|
||||
@@ -1354,6 +1371,12 @@ int freerdp_client_settings_command_line_status_print_ex(rdpSettings* settings,
|
||||
settings->ListMonitors = TRUE;
|
||||
}
|
||||
|
||||
arg = CommandLineFindArgumentA(largs, "smartcard-list");
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
{
|
||||
settings->ListSmartcards = TRUE;
|
||||
}
|
||||
|
||||
arg = CommandLineFindArgumentA(largs, "kbd-scancode-list");
|
||||
|
||||
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
|
||||
@@ -1565,7 +1588,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
if (!(arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "v")
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "v")
|
||||
{
|
||||
char* p;
|
||||
|
||||
@@ -1848,6 +1873,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
{
|
||||
settings->ListMonitors = enable;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "smartcard-list")
|
||||
{
|
||||
settings->ListSmartcards = enable;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "t")
|
||||
{
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_WindowTitle, arg->Value))
|
||||
@@ -3239,6 +3268,59 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
}
|
||||
}
|
||||
CommandLineSwitchCase(arg, "pin")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->Pin))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "pkcs11-module")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->Pkcs11Module))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "pkinit-anchors")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->PkinitAnchors))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "kerberos-start-time")
|
||||
{
|
||||
/* Let kinit parse time strings according to krb5_string_to_deltat syntax. */
|
||||
if (!copy_value(arg->Value, &settings->KerberosStartTime))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "kerberos-lifetime")
|
||||
{
|
||||
/* Let kinit parse time strings according to krb5_string_to_deltat syntax. */
|
||||
if (!copy_value(arg->Value, &settings->KerberosLifeTime))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "kerberos-renewable-lifetime")
|
||||
{
|
||||
/* Let kinit parse time strings according to krb5_string_to_deltat syntax. */
|
||||
if (!copy_value(arg->Value, &settings->KerberosRenewableLifeTime))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "csp")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->CspName))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "card")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->CardName))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "reader")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->ReaderName))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "container")
|
||||
{
|
||||
if (!copy_value(arg->Value, &settings->ContainerName))
|
||||
return COMMAND_LINE_ERROR_MEMORY;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "action-script")
|
||||
{
|
||||
if (!freerdp_settings_set_string(settings, FreeRDP_ActionScript, arg->Value))
|
||||
@@ -3263,18 +3345,21 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
} ptr;
|
||||
|
||||
settings->SmartcardLogon = TRUE;
|
||||
|
||||
ptr.p = CommandLineParseCommaSeparatedValuesEx("smartcard-logon", arg->Value, &count);
|
||||
if (ptr.pc)
|
||||
{
|
||||
size_t x;
|
||||
settings->SmartcardEmulation = TRUE;
|
||||
settings->SmartcardEmulation = (count > 1);
|
||||
for (x = 1; x < count; x++)
|
||||
{
|
||||
const char* cur = ptr.pc[x];
|
||||
if (strncmp("cert:", cur, 5) == 0)
|
||||
{
|
||||
const char* f = &cur[5];
|
||||
if (!read_pem_file(settings, FreeRDP_SmartcardCertificate, f))
|
||||
settings->SmartcardCertificateFile = strdup(f);
|
||||
if (!settings->SmartcardCertificateFile ||
|
||||
!read_pem_file(settings, FreeRDP_SmartcardCertificate, f))
|
||||
{
|
||||
free(ptr.p);
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
@@ -3283,7 +3368,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
else if (strncmp("key:", cur, 4) == 0)
|
||||
{
|
||||
const char* f = &cur[4];
|
||||
if (!read_pem_file(settings, FreeRDP_SmartcardPrivateKey, f))
|
||||
settings->SmartcardPrivateKeyFile = strdup(f);
|
||||
if (!settings->SmartcardPrivateKeyFile ||
|
||||
!read_pem_file(settings, FreeRDP_SmartcardPrivateKey, f))
|
||||
{
|
||||
free(ptr.p);
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
@@ -3307,7 +3394,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
}
|
||||
free(ptr.p);
|
||||
}
|
||||
|
||||
CommandLineSwitchCase(arg, "tune")
|
||||
{
|
||||
size_t x, count;
|
||||
@@ -3480,7 +3566,6 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
}
|
||||
|
||||
arg = CommandLineFindArgumentA(largs, "port");
|
||||
|
||||
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
||||
{
|
||||
LONGLONG val;
|
||||
@@ -3492,14 +3577,18 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
|
||||
}
|
||||
|
||||
arg = CommandLineFindArgumentA(largs, "p");
|
||||
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
||||
{
|
||||
FillMemory(arg->Value, strlen(arg->Value), '*');
|
||||
}
|
||||
|
||||
arg = CommandLineFindArgumentA(largs, "pin");
|
||||
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
||||
{
|
||||
FillMemory(arg->Value, strlen(arg->Value), '*');
|
||||
}
|
||||
|
||||
arg = CommandLineFindArgumentA(largs, "gp");
|
||||
|
||||
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)
|
||||
{
|
||||
FillMemory(arg->Value, strlen(arg->Value), '*');
|
||||
|
||||
@@ -224,6 +224,12 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
|
||||
{ "kbd-unicode", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, NULL,
|
||||
"Send unicode symbols, e.g. use the local keyboard map. ATTENTION: Does not work with every "
|
||||
"RDP server!" },
|
||||
{ "kerberos-start-time", COMMAND_LINE_VALUE_OPTIONAL, "<start time>", NULL, NULL, -1, NULL,
|
||||
"Kerberos Ticket start time" },
|
||||
{ "kerberos-lifetime", COMMAND_LINE_VALUE_OPTIONAL, "<lifetime>", NULL, NULL, -1, NULL,
|
||||
"Kerberos Ticket lifetime" },
|
||||
{ "kerberos-renewable-lifetime", COMMAND_LINE_VALUE_OPTIONAL, "<renewable lifetime>", NULL,
|
||||
NULL, -1, NULL, "Kerberos Ticket renewable lifetime" },
|
||||
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info-string>", NULL, NULL, -1, NULL,
|
||||
"Load balance info" },
|
||||
{ "log-filters", COMMAND_LINE_VALUE_REQUIRED, "<tag>:<level>[,<tag>:<level>[,...]]", NULL, NULL,
|
||||
@@ -239,6 +245,8 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
|
||||
{ "microphone", COMMAND_LINE_VALUE_OPTIONAL,
|
||||
"[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,][channel:<channel>]", NULL, NULL, -1,
|
||||
"mic", "Audio input (microphone)" },
|
||||
{ "smartcard-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL,
|
||||
"List smartcard informations" },
|
||||
{ "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL,
|
||||
"List detected monitors" },
|
||||
{ "monitors", COMMAND_LINE_VALUE_REQUIRED, "<id>[,<id>[,...]]", NULL, NULL, -1, NULL,
|
||||
@@ -278,8 +286,19 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
|
||||
"Use smart card authentication with password as smart card PIN" },
|
||||
{ "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
|
||||
{ "pcid", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Preconnection Id" },
|
||||
{ "card", COMMAND_LINE_VALUE_OPTIONAL, "<card name>", NULL, NULL, -1, NULL, "Card name" },
|
||||
{ "csp", COMMAND_LINE_VALUE_OPTIONAL, "<csp name>", NULL, NULL, -1, NULL, "CSP Name" },
|
||||
{ "reader", COMMAND_LINE_VALUE_OPTIONAL, "<reader name>", NULL, NULL, -1, NULL,
|
||||
"Card reader name" },
|
||||
{ "container", COMMAND_LINE_VALUE_OPTIONAL, "<container name>", NULL, NULL, -1, NULL,
|
||||
"Container name" },
|
||||
{ "pin", COMMAND_LINE_VALUE_REQUIRED, "<PIN code>", NULL, NULL, -1, NULL, "PIN code" },
|
||||
{ "pheight", COMMAND_LINE_VALUE_REQUIRED, "<height>", NULL, NULL, -1, NULL,
|
||||
"Physical height of display (in millimeters)" },
|
||||
{ "pkcs11-module", COMMAND_LINE_VALUE_OPTIONAL, "<module>", NULL, NULL, -1, NULL,
|
||||
"Module PKCS11" },
|
||||
{ "pkinit-anchors", COMMAND_LINE_VALUE_OPTIONAL, "<pkinit anchors>", NULL, NULL, -1, NULL,
|
||||
"PKINIT anchors" },
|
||||
{ "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "<pcap-file>", NULL, NULL, -1, NULL,
|
||||
"Replay rfx pcap file" },
|
||||
{ "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
|
||||
@@ -339,9 +358,7 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
|
||||
{ "smartcard", COMMAND_LINE_VALUE_OPTIONAL, "<str>[,<str>...]", NULL, NULL, -1, NULL,
|
||||
"Redirect the smartcard devices containing any of the <str> in their names." },
|
||||
{ "smartcard-logon", COMMAND_LINE_VALUE_OPTIONAL, "[cert:<path>,key:<key>,pin:<pin>]", NULL,
|
||||
NULL, -1, NULL,
|
||||
"Activates Smartcard (optional certificate) Logon authentication. (EXPERIMENTAL: NLA not "
|
||||
"supported)" },
|
||||
NULL, -1, NULL, "Activates Smartcard (optional certificate) Logon authentication." },
|
||||
{ "sound", COMMAND_LINE_VALUE_OPTIONAL,
|
||||
"[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,][channel:<channel>,][latency:<"
|
||||
"latency>,][quality:<quality>]",
|
||||
|
||||
@@ -54,6 +54,7 @@ extern "C"
|
||||
typedef struct crypto_cert_struct* CryptoCert;
|
||||
|
||||
FREERDP_API CryptoCert crypto_cert_read(const BYTE* data, UINT32 length);
|
||||
FREERDP_API CryptoCert crypto_cert_pem_read(const char* data);
|
||||
FREERDP_API BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length);
|
||||
FREERDP_API char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash);
|
||||
FREERDP_API char* crypto_cert_fingerprint_by_hash_ex(X509* xcert, const char* hash,
|
||||
|
||||
@@ -104,7 +104,8 @@ extern "C"
|
||||
AUTH_RDP,
|
||||
GW_AUTH_HTTP,
|
||||
GW_AUTH_RDG,
|
||||
GW_AUTH_RPC
|
||||
GW_AUTH_RPC,
|
||||
AUTH_SMARTCARD_PIN
|
||||
} rdp_auth_reason;
|
||||
|
||||
typedef BOOL (*pContextNew)(freerdp* instance, rdpContext* context);
|
||||
|
||||
@@ -663,8 +663,22 @@ typedef struct
|
||||
#define FreeRDP_SmartcardPrivateKey (1286)
|
||||
#define FreeRDP_SmartcardPin (1287)
|
||||
#define FreeRDP_SmartcardEmulation (1288)
|
||||
#define FreeRDP_SmartcardCertificateFile (1289)
|
||||
#define FreeRDP_SmartcardPrivateKeyFile (1290)
|
||||
#define FreeRDP_Pkcs11Module (1291)
|
||||
#define FreeRDP_Pin (1292)
|
||||
#define FreeRDP_KeySpec (1293)
|
||||
#define FreeRDP_CardName (1294)
|
||||
#define FreeRDP_ReaderName (1295)
|
||||
#define FreeRDP_ContainerName (1296)
|
||||
#define FreeRDP_CspName (1297)
|
||||
#define FreeRDP_PkinitAnchors (1298)
|
||||
#define FreeRDP_ListSmartcards (1299)
|
||||
#define FreeRDP_KerberosKdc (1344)
|
||||
#define FreeRDP_KerberosRealm (1345)
|
||||
#define FreeRDP_KerberosStartTime (1346)
|
||||
#define FreeRDP_KerberosLifeTime (1347)
|
||||
#define FreeRDP_KerberosRenewableLifeTime (1348)
|
||||
#define FreeRDP_IgnoreCertificate (1408)
|
||||
#define FreeRDP_CertificateName (1409)
|
||||
#define FreeRDP_CertificateFile (1410)
|
||||
@@ -1143,19 +1157,33 @@ struct rdp_settings
|
||||
ALIGN64 UINT32 Password51Length; /* 1281 */
|
||||
ALIGN64 BOOL SmartcardLogon; /* 1282 */
|
||||
ALIGN64 BOOL PromptForCredentials; /* 1283 */
|
||||
UINT64 padding1284[1285 - 1284]; /* 1284 */
|
||||
|
||||
/* Settings used for smartcard emulation */
|
||||
UINT64 padding1284[1285 - 1284]; /* 1284 */
|
||||
ALIGN64 char* SmartcardCertificate; /* 1285 */
|
||||
ALIGN64 char* SmartcardPrivateKey; /* 1286 */
|
||||
ALIGN64 char* SmartcardPin; /* 1287 */
|
||||
ALIGN64 BOOL SmartcardEmulation; /* 1288 */
|
||||
UINT64 padding1344[1344 - 1289]; /* 1289 */
|
||||
ALIGN64 char* SmartcardCertificate; /* 1285 */
|
||||
ALIGN64 char* SmartcardPrivateKey; /* 1286 */
|
||||
ALIGN64 char* SmartcardPin; /* 1287 */
|
||||
ALIGN64 BOOL SmartcardEmulation; /* 1288 */
|
||||
ALIGN64 char* SmartcardCertificateFile; /* 1289 */
|
||||
ALIGN64 char* SmartcardPrivateKeyFile; /* 1290 */
|
||||
ALIGN64 char* Pkcs11Module; /* 1291 */
|
||||
ALIGN64 char* Pin; /* 1292 */
|
||||
ALIGN64 UINT32 KeySpec; /* 1293 */
|
||||
ALIGN64 char* CardName; /* 1294 */
|
||||
ALIGN64 char* ReaderName; /* 1295 */
|
||||
ALIGN64 char* ContainerName; /* 1296 */
|
||||
ALIGN64 char* CspName; /* 1297 */
|
||||
ALIGN64 char* PkinitAnchors; /* 1298 */
|
||||
ALIGN64 BOOL ListSmartcards; /* 1299 */
|
||||
UINT64 padding1344[1344 - 1300]; /* 1300 */
|
||||
|
||||
/* Kerberos Authentication */
|
||||
ALIGN64 char* KerberosKdc; /* 1344 */
|
||||
ALIGN64 char* KerberosRealm; /* 1345 */
|
||||
UINT64 padding1408[1408 - 1346]; /* 1346 */
|
||||
ALIGN64 char* KerberosKdc; /* 1344 */
|
||||
ALIGN64 char* KerberosRealm; /* 1345 */
|
||||
ALIGN64 char* KerberosStartTime; /* 1346 */
|
||||
ALIGN64 char* KerberosLifeTime; /* 1347 */
|
||||
ALIGN64 char* KerberosRenewableLifeTime; /* 1348 */
|
||||
UINT64 padding1408[1408 - 1349]; /* 1349 */
|
||||
|
||||
/* Server Certificate */
|
||||
ALIGN64 BOOL IgnoreCertificate; /* 1408 */
|
||||
|
||||
37
include/freerdp/utils/smartcard_cli.h
Normal file
37
include/freerdp/utils/smartcard_cli.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Smartcard client functions
|
||||
*
|
||||
* Copyright 2021 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 UTILS_SMARTCARD_CLI_H__
|
||||
#define UTILS_SMARTCARD_CLI_H__
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/settings.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
FREERDP_API BOOL freerdp_smartcard_list(rdpSettings* settings);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* UTILS_SMARTCARD_CLI_H__ */
|
||||
@@ -291,6 +291,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_ListMonitors:
|
||||
return settings->ListMonitors;
|
||||
|
||||
case FreeRDP_ListSmartcards:
|
||||
return settings->ListSmartcards;
|
||||
|
||||
case FreeRDP_LocalConnection:
|
||||
return settings->LocalConnection;
|
||||
|
||||
@@ -920,6 +923,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val)
|
||||
settings->ListMonitors = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_ListSmartcards:
|
||||
settings->ListSmartcards = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_LocalConnection:
|
||||
settings->LocalConnection = cnv.c;
|
||||
break;
|
||||
@@ -1502,6 +1509,9 @@ UINT32 freerdp_settings_get_uint32(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_JpegQuality:
|
||||
return settings->JpegQuality;
|
||||
|
||||
case FreeRDP_KeySpec:
|
||||
return settings->KeySpec;
|
||||
|
||||
case FreeRDP_KeyboardCodePage:
|
||||
return settings->KeyboardCodePage;
|
||||
|
||||
@@ -1910,6 +1920,10 @@ BOOL freerdp_settings_set_uint32(rdpSettings* settings, size_t id, UINT32 val)
|
||||
settings->JpegQuality = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_KeySpec:
|
||||
settings->KeySpec = cnv.c;
|
||||
break;
|
||||
|
||||
case FreeRDP_KeyboardCodePage:
|
||||
settings->KeyboardCodePage = cnv.c;
|
||||
break;
|
||||
@@ -2340,6 +2354,9 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_AuthenticationServiceClass:
|
||||
return settings->AuthenticationServiceClass;
|
||||
|
||||
case FreeRDP_CardName:
|
||||
return settings->CardName;
|
||||
|
||||
case FreeRDP_CertificateAcceptedFingerprints:
|
||||
return settings->CertificateAcceptedFingerprints;
|
||||
|
||||
@@ -2373,6 +2390,12 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_ConnectionFile:
|
||||
return settings->ConnectionFile;
|
||||
|
||||
case FreeRDP_ContainerName:
|
||||
return settings->ContainerName;
|
||||
|
||||
case FreeRDP_CspName:
|
||||
return settings->CspName;
|
||||
|
||||
case FreeRDP_CurrentPath:
|
||||
return settings->CurrentPath;
|
||||
|
||||
@@ -2415,9 +2438,18 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_KerberosKdc:
|
||||
return settings->KerberosKdc;
|
||||
|
||||
case FreeRDP_KerberosLifeTime:
|
||||
return settings->KerberosLifeTime;
|
||||
|
||||
case FreeRDP_KerberosRealm:
|
||||
return settings->KerberosRealm;
|
||||
|
||||
case FreeRDP_KerberosRenewableLifeTime:
|
||||
return settings->KerberosRenewableLifeTime;
|
||||
|
||||
case FreeRDP_KerberosStartTime:
|
||||
return settings->KerberosStartTime;
|
||||
|
||||
case FreeRDP_KeyboardRemappingList:
|
||||
return settings->KeyboardRemappingList;
|
||||
|
||||
@@ -2430,6 +2462,15 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_PasswordHash:
|
||||
return settings->PasswordHash;
|
||||
|
||||
case FreeRDP_Pin:
|
||||
return settings->Pin;
|
||||
|
||||
case FreeRDP_Pkcs11Module:
|
||||
return settings->Pkcs11Module;
|
||||
|
||||
case FreeRDP_PkinitAnchors:
|
||||
return settings->PkinitAnchors;
|
||||
|
||||
case FreeRDP_PlayRemoteFxFile:
|
||||
return settings->PlayRemoteFxFile;
|
||||
|
||||
@@ -2460,6 +2501,9 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_RdpKeyFile:
|
||||
return settings->RdpKeyFile;
|
||||
|
||||
case FreeRDP_ReaderName:
|
||||
return settings->ReaderName;
|
||||
|
||||
case FreeRDP_RedirectionAcceptedCert:
|
||||
return settings->RedirectionAcceptedCert;
|
||||
|
||||
@@ -2517,12 +2561,18 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
case FreeRDP_SmartcardCertificate:
|
||||
return settings->SmartcardCertificate;
|
||||
|
||||
case FreeRDP_SmartcardCertificateFile:
|
||||
return settings->SmartcardCertificateFile;
|
||||
|
||||
case FreeRDP_SmartcardPin:
|
||||
return settings->SmartcardPin;
|
||||
|
||||
case FreeRDP_SmartcardPrivateKey:
|
||||
return settings->SmartcardPrivateKey;
|
||||
|
||||
case FreeRDP_SmartcardPrivateKeyFile:
|
||||
return settings->SmartcardPrivateKeyFile;
|
||||
|
||||
case FreeRDP_TargetNetAddress:
|
||||
return settings->TargetNetAddress;
|
||||
|
||||
@@ -2568,6 +2618,9 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
case FreeRDP_AuthenticationServiceClass:
|
||||
return settings->AuthenticationServiceClass;
|
||||
|
||||
case FreeRDP_CardName:
|
||||
return settings->CardName;
|
||||
|
||||
case FreeRDP_CertificateAcceptedFingerprints:
|
||||
return settings->CertificateAcceptedFingerprints;
|
||||
|
||||
@@ -2601,6 +2654,12 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
case FreeRDP_ConnectionFile:
|
||||
return settings->ConnectionFile;
|
||||
|
||||
case FreeRDP_ContainerName:
|
||||
return settings->ContainerName;
|
||||
|
||||
case FreeRDP_CspName:
|
||||
return settings->CspName;
|
||||
|
||||
case FreeRDP_CurrentPath:
|
||||
return settings->CurrentPath;
|
||||
|
||||
@@ -2643,9 +2702,18 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
case FreeRDP_KerberosKdc:
|
||||
return settings->KerberosKdc;
|
||||
|
||||
case FreeRDP_KerberosLifeTime:
|
||||
return settings->KerberosLifeTime;
|
||||
|
||||
case FreeRDP_KerberosRealm:
|
||||
return settings->KerberosRealm;
|
||||
|
||||
case FreeRDP_KerberosRenewableLifeTime:
|
||||
return settings->KerberosRenewableLifeTime;
|
||||
|
||||
case FreeRDP_KerberosStartTime:
|
||||
return settings->KerberosStartTime;
|
||||
|
||||
case FreeRDP_KeyboardRemappingList:
|
||||
return settings->KeyboardRemappingList;
|
||||
|
||||
@@ -2658,6 +2726,15 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
case FreeRDP_PasswordHash:
|
||||
return settings->PasswordHash;
|
||||
|
||||
case FreeRDP_Pin:
|
||||
return settings->Pin;
|
||||
|
||||
case FreeRDP_Pkcs11Module:
|
||||
return settings->Pkcs11Module;
|
||||
|
||||
case FreeRDP_PkinitAnchors:
|
||||
return settings->PkinitAnchors;
|
||||
|
||||
case FreeRDP_PlayRemoteFxFile:
|
||||
return settings->PlayRemoteFxFile;
|
||||
|
||||
@@ -2688,6 +2765,9 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
case FreeRDP_RdpKeyFile:
|
||||
return settings->RdpKeyFile;
|
||||
|
||||
case FreeRDP_ReaderName:
|
||||
return settings->ReaderName;
|
||||
|
||||
case FreeRDP_RedirectionAcceptedCert:
|
||||
return settings->RedirectionAcceptedCert;
|
||||
|
||||
@@ -2745,9 +2825,18 @@ char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
case FreeRDP_SmartcardCertificate:
|
||||
return settings->SmartcardCertificate;
|
||||
|
||||
case FreeRDP_SmartcardCertificateFile:
|
||||
return settings->SmartcardCertificateFile;
|
||||
|
||||
case FreeRDP_SmartcardPin:
|
||||
return settings->SmartcardPin;
|
||||
|
||||
case FreeRDP_SmartcardPrivateKey:
|
||||
return settings->SmartcardPrivateKey;
|
||||
|
||||
case FreeRDP_SmartcardPrivateKeyFile:
|
||||
return settings->SmartcardPrivateKeyFile;
|
||||
|
||||
case FreeRDP_TargetNetAddress:
|
||||
return settings->TargetNetAddress;
|
||||
|
||||
@@ -2803,6 +2892,9 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
|
||||
case FreeRDP_AuthenticationServiceClass:
|
||||
return update_string(&settings->AuthenticationServiceClass, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_CardName:
|
||||
return update_string(&settings->CardName, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_CertificateAcceptedFingerprints:
|
||||
return update_string(&settings->CertificateAcceptedFingerprints, cnv.cc, len, cleanup);
|
||||
|
||||
@@ -2836,6 +2928,12 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
|
||||
case FreeRDP_ConnectionFile:
|
||||
return update_string(&settings->ConnectionFile, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_ContainerName:
|
||||
return update_string(&settings->ContainerName, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_CspName:
|
||||
return update_string(&settings->CspName, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_CurrentPath:
|
||||
return update_string(&settings->CurrentPath, cnv.cc, len, cleanup);
|
||||
|
||||
@@ -2878,9 +2976,18 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
|
||||
case FreeRDP_KerberosKdc:
|
||||
return update_string(&settings->KerberosKdc, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_KerberosLifeTime:
|
||||
return update_string(&settings->KerberosLifeTime, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_KerberosRealm:
|
||||
return update_string(&settings->KerberosRealm, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_KerberosRenewableLifeTime:
|
||||
return update_string(&settings->KerberosRenewableLifeTime, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_KerberosStartTime:
|
||||
return update_string(&settings->KerberosStartTime, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_KeyboardRemappingList:
|
||||
return update_string(&settings->KeyboardRemappingList, cnv.cc, len, cleanup);
|
||||
|
||||
@@ -2893,6 +3000,15 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
|
||||
case FreeRDP_PasswordHash:
|
||||
return update_string(&settings->PasswordHash, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_Pin:
|
||||
return update_string(&settings->Pin, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_Pkcs11Module:
|
||||
return update_string(&settings->Pkcs11Module, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_PkinitAnchors:
|
||||
return update_string(&settings->PkinitAnchors, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_PlayRemoteFxFile:
|
||||
return update_string(&settings->PlayRemoteFxFile, cnv.cc, len, cleanup);
|
||||
|
||||
@@ -2923,6 +3039,9 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
|
||||
case FreeRDP_RdpKeyFile:
|
||||
return update_string(&settings->RdpKeyFile, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_ReaderName:
|
||||
return update_string(&settings->ReaderName, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_RedirectionAcceptedCert:
|
||||
return update_string(&settings->RedirectionAcceptedCert, cnv.cc, len, cleanup);
|
||||
|
||||
@@ -2980,12 +3099,18 @@ BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char*
|
||||
case FreeRDP_SmartcardCertificate:
|
||||
return update_string(&settings->SmartcardCertificate, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_SmartcardCertificateFile:
|
||||
return update_string(&settings->SmartcardCertificateFile, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_SmartcardPin:
|
||||
return update_string(&settings->SmartcardPin, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_SmartcardPrivateKey:
|
||||
return update_string(&settings->SmartcardPrivateKey, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_SmartcardPrivateKeyFile:
|
||||
return update_string(&settings->SmartcardPrivateKeyFile, cnv.cc, len, cleanup);
|
||||
|
||||
case FreeRDP_TargetNetAddress:
|
||||
return update_string(&settings->TargetNetAddress, cnv.cc, len, cleanup);
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_IgnoreCertificate, 0, "FreeRDP_IgnoreCertificate" },
|
||||
{ FreeRDP_JpegCodec, 0, "FreeRDP_JpegCodec" },
|
||||
{ FreeRDP_ListMonitors, 0, "FreeRDP_ListMonitors" },
|
||||
{ FreeRDP_ListSmartcards, 0, "FreeRDP_ListSmartcards" },
|
||||
{ FreeRDP_LocalConnection, 0, "FreeRDP_LocalConnection" },
|
||||
{ FreeRDP_LogonErrors, 0, "FreeRDP_LogonErrors" },
|
||||
{ FreeRDP_LogonNotify, 0, "FreeRDP_LogonNotify" },
|
||||
@@ -235,6 +236,7 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_GlyphSupportLevel, 3, "FreeRDP_GlyphSupportLevel" },
|
||||
{ FreeRDP_JpegCodecId, 3, "FreeRDP_JpegCodecId" },
|
||||
{ FreeRDP_JpegQuality, 3, "FreeRDP_JpegQuality" },
|
||||
{ FreeRDP_KeySpec, 3, "FreeRDP_KeySpec" },
|
||||
{ FreeRDP_KeyboardCodePage, 3, "FreeRDP_KeyboardCodePage" },
|
||||
{ FreeRDP_KeyboardFunctionKey, 3, "FreeRDP_KeyboardFunctionKey" },
|
||||
{ FreeRDP_KeyboardHook, 3, "FreeRDP_KeyboardHook" },
|
||||
@@ -313,6 +315,7 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_AlternateShell, 7, "FreeRDP_AlternateShell" },
|
||||
{ FreeRDP_AssistanceFile, 7, "FreeRDP_AssistanceFile" },
|
||||
{ FreeRDP_AuthenticationServiceClass, 7, "FreeRDP_AuthenticationServiceClass" },
|
||||
{ FreeRDP_CardName, 7, "FreeRDP_CardName" },
|
||||
{ FreeRDP_CertificateAcceptedFingerprints, 7, "FreeRDP_CertificateAcceptedFingerprints" },
|
||||
{ FreeRDP_CertificateContent, 7, "FreeRDP_CertificateContent" },
|
||||
{ FreeRDP_CertificateFile, 7, "FreeRDP_CertificateFile" },
|
||||
@@ -324,6 +327,8 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_ComputerName, 7, "FreeRDP_ComputerName" },
|
||||
{ FreeRDP_ConfigPath, 7, "FreeRDP_ConfigPath" },
|
||||
{ FreeRDP_ConnectionFile, 7, "FreeRDP_ConnectionFile" },
|
||||
{ FreeRDP_ContainerName, 7, "FreeRDP_ContainerName" },
|
||||
{ FreeRDP_CspName, 7, "FreeRDP_CspName" },
|
||||
{ FreeRDP_CurrentPath, 7, "FreeRDP_CurrentPath" },
|
||||
{ FreeRDP_Domain, 7, "FreeRDP_Domain" },
|
||||
{ FreeRDP_DrivesToRedirect, 7, "FreeRDP_DrivesToRedirect" },
|
||||
@@ -338,11 +343,17 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_HomePath, 7, "FreeRDP_HomePath" },
|
||||
{ FreeRDP_ImeFileName, 7, "FreeRDP_ImeFileName" },
|
||||
{ FreeRDP_KerberosKdc, 7, "FreeRDP_KerberosKdc" },
|
||||
{ FreeRDP_KerberosLifeTime, 7, "FreeRDP_KerberosLifeTime" },
|
||||
{ FreeRDP_KerberosRealm, 7, "FreeRDP_KerberosRealm" },
|
||||
{ FreeRDP_KerberosRenewableLifeTime, 7, "FreeRDP_KerberosRenewableLifeTime" },
|
||||
{ FreeRDP_KerberosStartTime, 7, "FreeRDP_KerberosStartTime" },
|
||||
{ FreeRDP_KeyboardRemappingList, 7, "FreeRDP_KeyboardRemappingList" },
|
||||
{ FreeRDP_NtlmSamFile, 7, "FreeRDP_NtlmSamFile" },
|
||||
{ FreeRDP_Password, 7, "FreeRDP_Password" },
|
||||
{ FreeRDP_PasswordHash, 7, "FreeRDP_PasswordHash" },
|
||||
{ FreeRDP_Pin, 7, "FreeRDP_Pin" },
|
||||
{ FreeRDP_Pkcs11Module, 7, "FreeRDP_Pkcs11Module" },
|
||||
{ FreeRDP_PkinitAnchors, 7, "FreeRDP_PkinitAnchors" },
|
||||
{ FreeRDP_PlayRemoteFxFile, 7, "FreeRDP_PlayRemoteFxFile" },
|
||||
{ FreeRDP_PreconnectionBlob, 7, "FreeRDP_PreconnectionBlob" },
|
||||
{ FreeRDP_PrivateKeyContent, 7, "FreeRDP_PrivateKeyContent" },
|
||||
@@ -353,6 +364,7 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_RDP2TCPArgs, 7, "FreeRDP_RDP2TCPArgs" },
|
||||
{ FreeRDP_RdpKeyContent, 7, "FreeRDP_RdpKeyContent" },
|
||||
{ FreeRDP_RdpKeyFile, 7, "FreeRDP_RdpKeyFile" },
|
||||
{ FreeRDP_ReaderName, 7, "FreeRDP_ReaderName" },
|
||||
{ FreeRDP_RedirectionAcceptedCert, 7, "FreeRDP_RedirectionAcceptedCert" },
|
||||
{ FreeRDP_RedirectionDomain, 7, "FreeRDP_RedirectionDomain" },
|
||||
{ FreeRDP_RedirectionTargetFQDN, 7, "FreeRDP_RedirectionTargetFQDN" },
|
||||
@@ -372,8 +384,10 @@ static const struct settings_str_entry settings_map[] = {
|
||||
{ FreeRDP_ServerHostname, 7, "FreeRDP_ServerHostname" },
|
||||
{ FreeRDP_ShellWorkingDirectory, 7, "FreeRDP_ShellWorkingDirectory" },
|
||||
{ FreeRDP_SmartcardCertificate, 7, "FreeRDP_SmartcardCertificate" },
|
||||
{ FreeRDP_SmartcardCertificateFile, 7, "FreeRDP_SmartcardCertificateFile" },
|
||||
{ FreeRDP_SmartcardPin, 7, "FreeRDP_SmartcardPin" },
|
||||
{ FreeRDP_SmartcardPrivateKey, 7, "FreeRDP_SmartcardPrivateKey" },
|
||||
{ FreeRDP_SmartcardPrivateKeyFile, 7, "FreeRDP_SmartcardPrivateKeyFile" },
|
||||
{ FreeRDP_TargetNetAddress, 7, "FreeRDP_TargetNetAddress" },
|
||||
{ FreeRDP_TransportDumpFile, 7, "FreeRDP_TransportDumpFile" },
|
||||
{ FreeRDP_Username, 7, "FreeRDP_Username" },
|
||||
|
||||
@@ -63,6 +63,10 @@ set(${MODULE_PREFIX}_SRCS
|
||||
mcs.h
|
||||
nla.c
|
||||
nla.h
|
||||
smartcardlogon.c
|
||||
smartcardlogon.h
|
||||
tscredentials.c
|
||||
tscredentials.h
|
||||
nego.c
|
||||
nego.h
|
||||
info.c
|
||||
|
||||
@@ -42,9 +42,13 @@
|
||||
#include <winpr/dsparse.h>
|
||||
#include <winpr/library.h>
|
||||
#include <winpr/registry.h>
|
||||
#include <winpr/ncrypt.h>
|
||||
#include <winpr/cred.h>
|
||||
|
||||
#include "nla.h"
|
||||
#include "utils.h"
|
||||
#include "tscredentials.h"
|
||||
#include "smartcardlogon.h"
|
||||
|
||||
#define TAG FREERDP_TAG("core.nla")
|
||||
|
||||
@@ -134,7 +138,11 @@ struct rdp_nla
|
||||
SecBuffer tsCredentials;
|
||||
|
||||
LPTSTR ServicePrincipalName;
|
||||
void* identityPtr;
|
||||
SEC_WINNT_AUTH_IDENTITY* identity;
|
||||
SEC_WINNT_AUTH_IDENTITY_EXW identityEx;
|
||||
SEC_WINNT_AUTH_IDENTITY_WINPRA identityWinPr;
|
||||
SEC_WINPR_KERBEROS_SETTINGS kerberosSettings;
|
||||
PSecurityFunctionTable table;
|
||||
SecPkgContext_Sizes ContextSizes;
|
||||
};
|
||||
@@ -386,6 +394,7 @@ static SECURITY_STATUS nla_decrypt(rdpNla* nla, SecBuffer* buffer, size_t header
|
||||
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
|
||||
Buffers[0].cbBuffer = (ULONG)headerLength;
|
||||
Buffers[0].pvBuffer = &((BYTE*)buffer->pvBuffer)[0];
|
||||
|
||||
Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
|
||||
Buffers[1].cbBuffer = (ULONG)(buffer->cbBuffer - headerLength);
|
||||
Buffers[1].pvBuffer = &((BYTE*)buffer->pvBuffer)[headerLength];
|
||||
@@ -430,6 +439,7 @@ static SECURITY_STATUS nla_encrypt(rdpNla* nla, SecBuffer* buffer, size_t header
|
||||
Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
|
||||
Buffers[0].cbBuffer = (ULONG)headerLength;
|
||||
Buffers[0].pvBuffer = &((BYTE*)buffer->pvBuffer)[0];
|
||||
|
||||
Buffers[1].BufferType = SECBUFFER_DATA;
|
||||
Buffers[1].cbBuffer = (ULONG)(buffer->cbBuffer - headerLength);
|
||||
Buffers[1].pvBuffer = &((BYTE*)buffer->pvBuffer)[headerLength];
|
||||
@@ -526,29 +536,218 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
|
||||
free(identity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize NTLM/Kerberos SSP authentication module (client).
|
||||
* @param credssp
|
||||
*/
|
||||
|
||||
static int nla_client_init(rdpNla* nla)
|
||||
static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
|
||||
{
|
||||
char* spn;
|
||||
size_t length;
|
||||
rdpTls* tls = NULL;
|
||||
BOOL PromptPassword = FALSE;
|
||||
freerdp* instance = nla->instance;
|
||||
#define MAX_SC_CERTS 64
|
||||
SmartcardCert certs[MAX_SC_CERTS];
|
||||
DWORD count, i = 0;
|
||||
rdpSettings* settings = nla->settings;
|
||||
SEC_WINPR_KERBEROS_SETTINGS* kerbSettings = &nla->kerberosSettings;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!settings->CspName)
|
||||
{
|
||||
settings->CspName = strdup(MS_SCARD_PROV_A);
|
||||
if (!settings->CspName)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to set CSP name");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings->PkinitAnchors)
|
||||
{
|
||||
kerbSettings->pkinitX509Anchors = _strdup(settings->PkinitAnchors);
|
||||
if (!kerbSettings->pkinitX509Anchors)
|
||||
{
|
||||
WLog_ERR(TAG, "error setting X509 anchors");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!smartcard_enumerateCerts(settings, certs, MAX_SC_CERTS, &count))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to list smartcard certificates");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!count)
|
||||
{
|
||||
WLog_ERR(TAG, "no smartcard certificates found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (count != 1)
|
||||
goto setup_pin;
|
||||
|
||||
/*
|
||||
* just one result let's try to fill missing parameters
|
||||
*/
|
||||
if (!settings->Username && certs[0].userHint)
|
||||
{
|
||||
settings->Username = strdup(certs[0].userHint);
|
||||
if (!settings->Username)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy certificate username");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->Domain && certs[0].domainHint)
|
||||
{
|
||||
settings->Domain = strdup(certs[0].domainHint);
|
||||
if (!settings->Domain)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy certificate domain");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->ReaderName && certs[0].reader)
|
||||
{
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, certs[0].reader, -1, &settings->ReaderName, 0, NULL,
|
||||
NULL) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy reader name");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!settings->ContainerName && certs[0].containerName)
|
||||
{
|
||||
settings->ContainerName = strdup(certs[0].containerName);
|
||||
if (!settings->ContainerName)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy container name");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(nla->kerberosSettings.certSha1, certs[0].sha1Hash,
|
||||
sizeof(nla->kerberosSettings.certSha1));
|
||||
|
||||
#ifndef _WIN32
|
||||
if (certs[0].pkinitArgs)
|
||||
{
|
||||
kerbSettings->pkinitX509Identity = strdup(certs[0].pkinitArgs);
|
||||
if (!kerbSettings->pkinitX509Identity)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to copy pkinitArgs");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
setup_pin:
|
||||
if (!settings->Pin)
|
||||
{
|
||||
if (settings->SmartcardEmulation)
|
||||
{
|
||||
const char* dupSrc = settings->SmartcardPin;
|
||||
if (!dupSrc)
|
||||
dupSrc = "";
|
||||
|
||||
settings->Pin = strdup(dupSrc);
|
||||
if (!settings->Pin)
|
||||
{
|
||||
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->Pin,
|
||||
&settings->Domain, AUTH_SMARTCARD_PIN))
|
||||
{
|
||||
WLog_ERR(TAG, "no pin code entered");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
for (i = 0; i < count; i++)
|
||||
smartcardCert_Free(&certs[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL nla_client_setup_identity(rdpNla* nla)
|
||||
{
|
||||
WINPR_SAM* sam;
|
||||
WINPR_SAM_ENTRY* entry;
|
||||
nla_set_state(nla, NLA_STATE_INITIAL);
|
||||
BOOL PromptPassword = FALSE;
|
||||
rdpSettings* settings = nla->settings;
|
||||
freerdp* instance = nla->instance;
|
||||
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
settings->DisableCredentialsDelegation = TRUE;
|
||||
if (settings->SmartcardLogon)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_EXW* identityEx;
|
||||
CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), { 0 } };
|
||||
LPWSTR marshalledCredentials;
|
||||
|
||||
if (utils_str_is_empty(settings->Username) ||
|
||||
(utils_str_is_empty(settings->Password) &&
|
||||
utils_str_is_empty((const char*)settings->RedirectionPassword)))
|
||||
identityEx = &nla->identityEx;
|
||||
memcpy(certInfo.rgbHashOfCert, nla->kerberosSettings.certSha1,
|
||||
sizeof(certInfo.rgbHashOfCert));
|
||||
|
||||
if (!CredMarshalCredentialW(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 = (PUSHORT)marshalledCredentials;
|
||||
identityEx->UserLength = _wcslen(marshalledCredentials);
|
||||
if (ConvertToUnicode(CP_UTF8, 0, settings->Pin, -1, &identityEx->Password, 0) <= 0)
|
||||
return FALSE;
|
||||
identityEx->PasswordLength = strlen(settings->Pin);
|
||||
identityEx->Domain = NULL;
|
||||
identityEx->DomainLength = 0;
|
||||
identityEx->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
||||
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*)strdup(settings->Pin);
|
||||
identityEx->PasswordLength = strlen(settings->Pin);
|
||||
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) ||
|
||||
(utils_str_is_empty(settings->Password) &&
|
||||
utils_str_is_empty((const char*)settings->RedirectionPassword))))
|
||||
{
|
||||
PromptPassword = TRUE;
|
||||
}
|
||||
@@ -556,11 +755,9 @@ static int nla_client_init(rdpNla* nla)
|
||||
if (PromptPassword && !utils_str_is_empty(settings->Username))
|
||||
{
|
||||
sam = SamOpen(NULL, TRUE);
|
||||
|
||||
if (sam)
|
||||
{
|
||||
entry = SamLookupUserA(sam, settings->Username, strlen(settings->Username), NULL, 0);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
/**
|
||||
@@ -576,7 +773,6 @@ static int nla_client_init(rdpNla* nla)
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
if (PromptPassword)
|
||||
{
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
@@ -585,7 +781,6 @@ static int nla_client_init(rdpNla* nla)
|
||||
PromptPassword = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (PromptPassword)
|
||||
@@ -611,6 +806,8 @@ static int nla_client_init(rdpNla* nla)
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL usePassword = TRUE;
|
||||
|
||||
if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
|
||||
{
|
||||
if (sspi_SetAuthIdentityWithUnicodePassword(
|
||||
@@ -619,40 +816,59 @@ static int nla_client_init(rdpNla* nla)
|
||||
settings->RedirectionPasswordLength / sizeof(WCHAR) - 1) < 0)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
{
|
||||
BOOL usePassword = TRUE;
|
||||
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
{
|
||||
if (settings->PasswordHash)
|
||||
{
|
||||
if (strlen(settings->PasswordHash) == 32)
|
||||
{
|
||||
if (sspi_SetAuthIdentity(nla->identity, settings->Username,
|
||||
settings->Domain, settings->PasswordHash) < 0)
|
||||
return -1;
|
||||
|
||||
/**
|
||||
* Increase password hash length by LB_PASSWORD_MAX_LENGTH to obtain a
|
||||
* length exceeding the maximum (LB_PASSWORD_MAX_LENGTH) and use it this for
|
||||
* hash identification in WinPR.
|
||||
*/
|
||||
nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
|
||||
usePassword = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usePassword)
|
||||
if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
|
||||
{
|
||||
if (sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
|
||||
settings->Password) < 0)
|
||||
settings->PasswordHash) < 0)
|
||||
return -1;
|
||||
|
||||
/**
|
||||
* Increase password hash length by LB_PASSWORD_MAX_LENGTH to obtain a
|
||||
* length exceeding the maximum (LB_PASSWORD_MAX_LENGTH) and use it this for
|
||||
* hash identification in WinPR.
|
||||
*/
|
||||
nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
|
||||
usePassword = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (usePassword)
|
||||
{
|
||||
if (sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
|
||||
settings->Password) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize NTLM/Kerberos SSP authentication module (client).
|
||||
* @param credssp
|
||||
*/
|
||||
|
||||
static int nla_client_init(rdpNla* nla)
|
||||
{
|
||||
char* spn;
|
||||
size_t length;
|
||||
rdpTls* tls = NULL;
|
||||
rdpSettings* settings = nla->settings;
|
||||
|
||||
nla_set_state(nla, NLA_STATE_INITIAL);
|
||||
|
||||
if (settings->RestrictedAdminModeRequired)
|
||||
settings->DisableCredentialsDelegation = TRUE;
|
||||
|
||||
if (settings->SmartcardLogon && !nla_adjust_settings_from_smartcard(nla))
|
||||
return -1;
|
||||
|
||||
if (!nla_client_setup_identity(nla))
|
||||
return -1;
|
||||
|
||||
tls = transport_get_tls(nla->transport);
|
||||
|
||||
if (!tls)
|
||||
@@ -689,7 +905,7 @@ static int nla_client_init(rdpNla* nla)
|
||||
WLog_DBG(TAG, "%s %" PRIu32 " : packageName=%ls ; cbMaxToken=%d", __FUNCTION__, __LINE__,
|
||||
nla->packageName, nla->cbMaxToken);
|
||||
nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_OUTBOUND,
|
||||
NULL, nla->identity, NULL, NULL,
|
||||
NULL, nla->identityPtr, NULL, NULL,
|
||||
&nla->credentials, &nla->expiration);
|
||||
|
||||
if (nla->status != SEC_E_OK)
|
||||
@@ -892,7 +1108,6 @@ static int nla_client_recv_pub_key_auth(rdpNla* nla)
|
||||
|
||||
/* Send encrypted credentials */
|
||||
nla->status = nla_encrypt_ts_credentials(nla);
|
||||
|
||||
if (nla->status != SEC_E_OK)
|
||||
return -1;
|
||||
|
||||
@@ -1576,30 +1791,6 @@ fail:
|
||||
return status;
|
||||
}
|
||||
|
||||
static size_t nla_sizeof_ts_password_creds(rdpNla* nla)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (nla->identity)
|
||||
{
|
||||
length += ber_sizeof_sequence_octet_string(nla->identity->DomainLength * 2);
|
||||
length += ber_sizeof_sequence_octet_string(nla->identity->UserLength * 2);
|
||||
length += ber_sizeof_sequence_octet_string(nla->identity->PasswordLength * 2);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static size_t nla_sizeof_ts_credentials(rdpNla* nla)
|
||||
{
|
||||
size_t size = 0;
|
||||
size += ber_sizeof_integer(1);
|
||||
size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
|
||||
size +=
|
||||
ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
|
||||
return size;
|
||||
}
|
||||
|
||||
BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
|
||||
{
|
||||
size_t length;
|
||||
@@ -1691,29 +1882,6 @@ BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static size_t nla_write_ts_password_creds(rdpNla* nla, wStream* s)
|
||||
{
|
||||
size_t size = 0;
|
||||
size_t innerSize = nla_sizeof_ts_password_creds(nla);
|
||||
/* TSPasswordCreds (SEQUENCE) */
|
||||
size += ber_write_sequence_tag(s, innerSize);
|
||||
|
||||
if (nla->identity)
|
||||
{
|
||||
/* [0] domainName (OCTET STRING) */
|
||||
size += ber_write_sequence_octet_string(s, 0, (BYTE*)nla->identity->Domain,
|
||||
nla->identity->DomainLength * 2);
|
||||
/* [1] userName (OCTET STRING) */
|
||||
size += ber_write_sequence_octet_string(s, 1, (BYTE*)nla->identity->User,
|
||||
nla->identity->UserLength * 2);
|
||||
/* [2] password (OCTET STRING) */
|
||||
size += ber_write_sequence_octet_string(s, 2, (BYTE*)nla->identity->Password,
|
||||
nla->identity->PasswordLength * 2);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data, size_t offset)
|
||||
{
|
||||
wStream* s;
|
||||
@@ -1748,23 +1916,6 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t nla_write_ts_credentials(rdpNla* nla, wStream* s)
|
||||
{
|
||||
size_t size = 0;
|
||||
size_t passwordSize;
|
||||
size_t innerSize = nla_sizeof_ts_credentials(nla);
|
||||
/* TSCredentials (SEQUENCE) */
|
||||
size += ber_write_sequence_tag(s, innerSize);
|
||||
/* [0] credType (INTEGER) */
|
||||
size += ber_write_contextual_tag(s, 0, ber_sizeof_integer(1), TRUE);
|
||||
size += ber_write_integer(s, 1);
|
||||
/* [1] credentials (OCTET STRING) */
|
||||
passwordSize = ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla));
|
||||
size += ber_write_contextual_tag(s, 1, ber_sizeof_octet_string(passwordSize), TRUE);
|
||||
size += ber_write_octet_string_tag(s, passwordSize);
|
||||
size += nla_write_ts_password_creds(nla, s);
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode TSCredentials structure.
|
||||
@@ -1773,57 +1924,88 @@ static size_t nla_write_ts_credentials(rdpNla* nla, wStream* s)
|
||||
|
||||
static BOOL nla_encode_ts_credentials(rdpNla* nla)
|
||||
{
|
||||
wStream* credsContentStream;
|
||||
wStream staticRetStream;
|
||||
wStream* s;
|
||||
size_t length;
|
||||
UINT32 DomainLength = 0;
|
||||
UINT32 UserLength = 0;
|
||||
UINT32 PasswordLength = 0;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (nla->identity)
|
||||
TSCredentials_t cr = { 0 };
|
||||
rdpSettings* settings = nla->settings;
|
||||
|
||||
if (settings->SmartcardLogon)
|
||||
{
|
||||
/* TSPasswordCreds */
|
||||
DomainLength = nla->identity->DomainLength;
|
||||
UserLength = nla->identity->UserLength;
|
||||
PasswordLength = nla->identity->PasswordLength;
|
||||
TSSmartCardCreds_t smartcardCreds = { 0 };
|
||||
TSCspDataDetail_t cspData = { 0 };
|
||||
|
||||
if (settings->SmartcardEmulation)
|
||||
smartcardCreds.pin = settings->SmartcardPin;
|
||||
if (!smartcardCreds.pin)
|
||||
smartcardCreds.pin = settings->Pin ? settings->Pin : "";
|
||||
/*smartcardCreds.userHint = settings->UserHint;
|
||||
smartcardCreds.domainHint = settings->DomainHint;*/
|
||||
smartcardCreds.cspData = &cspData;
|
||||
|
||||
cspData.keySpec = settings->KeySpec;
|
||||
cspData.cspName = settings->CspName;
|
||||
cspData.readerName = settings->ReaderName;
|
||||
cspData.cardName = settings->CardName;
|
||||
cspData.containerName = settings->ContainerName;
|
||||
|
||||
length = ber_sizeof_nla_TSSmartCardCreds(&smartcardCreds);
|
||||
credsContentStream = Stream_New(NULL, length);
|
||||
if (!credsContentStream)
|
||||
return FALSE;
|
||||
|
||||
if (ber_write_nla_TSSmartCardCreds(credsContentStream, &smartcardCreds) == 0)
|
||||
return FALSE;
|
||||
|
||||
cr.credType = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPasswordCreds_t passCreds = { 0 };
|
||||
|
||||
if (!nla->settings->DisableCredentialsDelegation && nla->identity)
|
||||
{
|
||||
passCreds.userNameLen = nla->identity->UserLength * 2;
|
||||
passCreds.userName = (BYTE*)nla->identity->User;
|
||||
|
||||
passCreds.domainNameLen = nla->identity->DomainLength * 2;
|
||||
passCreds.domainName = (BYTE*)nla->identity->Domain;
|
||||
|
||||
passCreds.passwordLen = nla->identity->PasswordLength * 2;
|
||||
passCreds.password = (BYTE*)nla->identity->Password;
|
||||
}
|
||||
|
||||
length = ber_sizeof_nla_TSPasswordCreds(&passCreds);
|
||||
credsContentStream = Stream_New(NULL, length);
|
||||
if (!credsContentStream)
|
||||
return FALSE;
|
||||
|
||||
ber_write_nla_TSPasswordCreds(credsContentStream, &passCreds);
|
||||
|
||||
cr.credType = 1;
|
||||
}
|
||||
|
||||
if (nla->settings->DisableCredentialsDelegation && nla->identity)
|
||||
{
|
||||
/* TSPasswordCreds */
|
||||
nla->identity->DomainLength = 0;
|
||||
nla->identity->UserLength = 0;
|
||||
nla->identity->PasswordLength = 0;
|
||||
}
|
||||
|
||||
length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla));
|
||||
cr.credentialsLen = length;
|
||||
cr.credentials = Stream_Buffer(credsContentStream);
|
||||
|
||||
length = ber_sizeof_nla_TSCredentials(&cr);
|
||||
if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
|
||||
{
|
||||
WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
|
||||
return FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = Stream_New((BYTE*)nla->tsCredentials.pvBuffer, length);
|
||||
s = Stream_StaticInit(&staticRetStream, (BYTE*)nla->tsCredentials.pvBuffer, length);
|
||||
ber_write_nla_TSCredentials(s, &cr);
|
||||
ret = TRUE;
|
||||
|
||||
if (!s)
|
||||
{
|
||||
sspi_SecBufferFree(&nla->tsCredentials);
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nla_write_ts_credentials(nla, s);
|
||||
|
||||
if (nla->settings->DisableCredentialsDelegation && nla->identity)
|
||||
{
|
||||
/* TSPasswordCreds */
|
||||
nla->identity->DomainLength = DomainLength;
|
||||
nla->identity->UserLength = UserLength;
|
||||
nla->identity->PasswordLength = PasswordLength;
|
||||
}
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
return TRUE;
|
||||
printf("creds=%s\n", winpr_BinToHexString((BYTE*)nla->tsCredentials.pvBuffer, length, TRUE));
|
||||
out:
|
||||
Stream_Free(credsContentStream, TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
|
||||
@@ -2289,6 +2471,7 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nla->identityPtr = nla->identity;
|
||||
nla->instance = instance;
|
||||
nla->settings = settings;
|
||||
nla->server = settings->ServerMode;
|
||||
@@ -2296,6 +2479,7 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
|
||||
nla->sendSeqNum = 0;
|
||||
nla->recvSeqNum = 0;
|
||||
nla->version = 6;
|
||||
nla->identityWinPr.kerberosSettings = &nla->kerberosSettings;
|
||||
SecInvalidateHandle(&nla->context);
|
||||
|
||||
if (settings->NtlmSamFile)
|
||||
|
||||
@@ -391,7 +391,8 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
||||
!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, 0) ||
|
||||
!freerdp_settings_set_uint32(settings, FreeRDP_ChannelDefArraySize, 32) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_CertificateUseKnownHosts, TRUE) ||
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, FALSE))
|
||||
!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, FALSE) ||
|
||||
!freerdp_settings_set_uint32(settings, FreeRDP_KeySpec, AT_KEYEXCHANGE))
|
||||
goto out_fail;
|
||||
|
||||
settings->ChannelDefArray = (CHANNEL_DEF*)calloc(
|
||||
|
||||
404
libfreerdp/core/smartcardlogon.c
Normal file
404
libfreerdp/core/smartcardlogon.c
Normal file
@@ -0,0 +1,404 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Logging in with smartcards
|
||||
*
|
||||
* Copyright 2022 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.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/objects.h>
|
||||
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/ncrypt.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/smartcard.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "smartcardlogon.h"
|
||||
|
||||
#define TAG FREERDP_TAG("smartcardlogon")
|
||||
|
||||
static BOOL getAtr(LPWSTR readerName, BYTE* atr, DWORD* atrLen)
|
||||
{
|
||||
WCHAR atrName[256];
|
||||
DWORD cbLength;
|
||||
DWORD dwShareMode = SCARD_SHARE_SHARED;
|
||||
DWORD dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
||||
SCARDHANDLE hCardHandle;
|
||||
DWORD dwActiveProtocol = 0;
|
||||
BOOL ret = FALSE;
|
||||
LONG status = 0;
|
||||
SCARDCONTEXT scContext;
|
||||
|
||||
status = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scContext);
|
||||
if (status != ERROR_SUCCESS || !scContext)
|
||||
return FALSE;
|
||||
|
||||
status = SCardConnectW(scContext, readerName, dwShareMode, dwPreferredProtocols, &hCardHandle,
|
||||
&dwActiveProtocol);
|
||||
if (status != ERROR_SUCCESS)
|
||||
goto out_connect;
|
||||
|
||||
*atrLen = 256;
|
||||
status = SCardGetAttrib(hCardHandle, SCARD_ATTR_ATR_STRING, atr, atrLen);
|
||||
if (status != ERROR_SUCCESS)
|
||||
goto out_get_attrib;
|
||||
|
||||
cbLength = 256;
|
||||
status = SCardListCardsW(scContext, atr, NULL, 0, atrName, &cbLength);
|
||||
if (status != ERROR_SUCCESS)
|
||||
goto out_listCards;
|
||||
|
||||
/* WLog_DBG(TAG, "ATR name: %ld -> %S\n", cbLength, atrName); */
|
||||
ret = TRUE;
|
||||
out_listCards:
|
||||
out_get_attrib:
|
||||
SCardDisconnect(scContext, SCARD_LEAVE_CARD);
|
||||
out_connect:
|
||||
SCardReleaseContext(scContext);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void smartcardCert_Free(SmartcardCert* scCert)
|
||||
{
|
||||
free(scCert->reader);
|
||||
crypto_cert_free(scCert->certificate);
|
||||
free(scCert->pkinitArgs);
|
||||
free(scCert->containerName);
|
||||
free(scCert->upn);
|
||||
free(scCert->userHint);
|
||||
free(scCert->domainHint);
|
||||
free(scCert->subject);
|
||||
free(scCert->issuer);
|
||||
|
||||
ZeroMemory(scCert, sizeof(*scCert));
|
||||
}
|
||||
|
||||
static BOOL treat_sc_cert(SmartcardCert* scCert)
|
||||
{
|
||||
scCert->upn = crypto_cert_get_upn(scCert->certificate->px509);
|
||||
if (scCert->upn)
|
||||
{
|
||||
size_t userLen;
|
||||
const char* atPos = strchr(scCert->upn, '@');
|
||||
|
||||
if (!atPos)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid UPN, for key %s (no @)", scCert->containerName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
userLen = (atPos - scCert->upn);
|
||||
scCert->userHint = malloc(userLen + 1);
|
||||
scCert->domainHint = strdup(atPos + 1);
|
||||
|
||||
if (!scCert->userHint || !scCert->domainHint)
|
||||
{
|
||||
WLog_ERR(TAG, "error allocating userHint or domainHint, for key %s",
|
||||
scCert->containerName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(scCert->userHint, scCert->upn, userLen);
|
||||
scCert->userHint[userLen] = 0;
|
||||
}
|
||||
|
||||
scCert->subject = crypto_cert_subject(scCert->certificate->px509);
|
||||
scCert->issuer = crypto_cert_issuer(scCert->certificate->px509);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static BOOL build_pkinit_args(rdpSettings* settings, SmartcardCert* scCert)
|
||||
{
|
||||
/* pkinit args only under windows
|
||||
* PKCS11:module_name=opensc-pkcs11.so
|
||||
*/
|
||||
size_t sz = strlen("PKCS11:module_name=:slotid=XXXXX");
|
||||
const char* pkModule = settings->Pkcs11Module ? settings->Pkcs11Module : "opensc-pkcs11.so";
|
||||
|
||||
sz += strlen(pkModule) + 1;
|
||||
|
||||
scCert->pkinitArgs = malloc(sz);
|
||||
if (!scCert->pkinitArgs)
|
||||
return FALSE;
|
||||
|
||||
snprintf(scCert->pkinitArgs, sz, "PKCS11:module_name=%s:slotid=%" PRIu16, pkModule,
|
||||
(UINT16)scCert->slotId);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
static BOOL smartcard_hw_enumerateCerts(rdpSettings* settings, LPCWSTR csp, const char* reader,
|
||||
const char* userFilter, SmartcardCert* scCert, DWORD count,
|
||||
DWORD* retCount)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
LPWSTR scope = NULL;
|
||||
PVOID enumState = NULL;
|
||||
NCRYPT_PROV_HANDLE provider;
|
||||
NCryptKeyName* keyName = NULL;
|
||||
SECURITY_STATUS status;
|
||||
|
||||
if (reader)
|
||||
{
|
||||
int res;
|
||||
size_t readerSz = strlen(reader);
|
||||
char* scopeStr = malloc(4 + readerSz + 1 + 1);
|
||||
if (!scopeStr)
|
||||
goto out;
|
||||
|
||||
snprintf(scopeStr, readerSz + 5, "\\\\.\\%s\\", reader);
|
||||
res = ConvertToUnicode(CP_UTF8, 0, scopeStr, -1, &scope, 0);
|
||||
free(scopeStr);
|
||||
|
||||
if (res <= 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = NCryptOpenStorageProvider(&provider, csp, 0);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to open provider");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*retCount = 0;
|
||||
while ((*retCount < count) && (status = NCryptEnumKeys(provider, scope, &keyName, &enumState,
|
||||
NCRYPT_SILENT_FLAG)) == ERROR_SUCCESS)
|
||||
{
|
||||
NCRYPT_KEY_HANDLE phKey;
|
||||
PBYTE certBytes = NULL;
|
||||
DWORD cbOutput;
|
||||
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, keyName->pszName, -1, &scCert->containerName, 0, NULL,
|
||||
NULL) <= 0)
|
||||
continue;
|
||||
|
||||
status = NCryptOpenKey(provider, &phKey, keyName->pszName, keyName->dwLegacyKeySpec,
|
||||
keyName->dwFlags);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
smartcardCert_Free(scCert);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
status = NCryptGetProperty(phKey, NCRYPT_WINPR_SLOTID, (PBYTE)&scCert->slotId, 4, &cbOutput,
|
||||
NCRYPT_SILENT_FLAG);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve slotId for key %s", scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/* ====== retrieve key's reader ====== */
|
||||
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, NULL, 0, &cbOutput,
|
||||
NCRYPT_SILENT_FLAG);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve reader's name length for key %s",
|
||||
scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
scCert->reader = calloc(1, cbOutput + 2);
|
||||
if (!scCert->reader)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate reader's name for key %s", scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, (PBYTE)scCert->reader,
|
||||
cbOutput + 2, &cbOutput, NCRYPT_SILENT_FLAG);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve reader's name for key %s", scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
if (!getAtr(scCert->reader, scCert->atr, &scCert->atrLength))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve card ATR for key %s", scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
/* ========= retrieve the certificate ===============*/
|
||||
status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, NULL, 0, &cbOutput,
|
||||
NCRYPT_SILENT_FLAG);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
/* can happen that key don't have certificates */
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
certBytes = calloc(1, cbOutput);
|
||||
if (!certBytes)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to allocate %d certBytes for key %s", cbOutput,
|
||||
scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, certBytes, cbOutput,
|
||||
&cbOutput, NCRYPT_SILENT_FLAG);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to retrieve certificate for key %s", scCert->containerName);
|
||||
free(certBytes);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
if (!winpr_Digest(WINPR_MD_SHA1, certBytes, cbOutput, scCert->sha1Hash,
|
||||
sizeof(scCert->sha1Hash)))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to compute certificate sha1 for key %s", scCert->containerName);
|
||||
free(certBytes);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
scCert->certificate = crypto_cert_read(certBytes, cbOutput);
|
||||
free(certBytes);
|
||||
|
||||
if (!scCert->certificate)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to parse X509 certificate for key %s", scCert->containerName);
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
if (!treat_sc_cert(scCert))
|
||||
{
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
if (userFilter && scCert->userHint && strcmp(scCert->userHint, userFilter) != 0)
|
||||
{
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!build_pkinit_args(settings, scCert))
|
||||
{
|
||||
WLog_ERR(TAG, "error build pkinit args");
|
||||
smartcardCert_Free(scCert);
|
||||
goto endofloop;
|
||||
}
|
||||
#endif
|
||||
|
||||
++*retCount;
|
||||
scCert++;
|
||||
|
||||
endofloop:
|
||||
NCryptFreeObject((NCRYPT_HANDLE)phKey);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
NCryptFreeObject((NCRYPT_HANDLE)provider);
|
||||
out:
|
||||
free(scope);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL smartcard_sw_enumerateCerts(rdpSettings* settings, SmartcardCert* scCert, DWORD count,
|
||||
DWORD* retCount)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
if (count < 1)
|
||||
return FALSE;
|
||||
|
||||
if (!settings->SmartcardCertificateFile || !settings->SmartcardPrivateKeyFile)
|
||||
{
|
||||
WLog_ERR(TAG, "missing smartcard emulation cert or key");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* compute PKINIT args FILE:<cert file>,<key file> */
|
||||
sz = strlen("FILE:") + strlen(settings->SmartcardCertificateFile) + 1 +
|
||||
strlen(settings->SmartcardPrivateKeyFile) + 1;
|
||||
scCert->pkinitArgs = malloc(sz);
|
||||
snprintf(scCert->pkinitArgs, sz, "FILE:%s,%s", settings->SmartcardCertificateFile,
|
||||
settings->SmartcardPrivateKeyFile);
|
||||
|
||||
scCert->certificate = crypto_cert_pem_read(settings->SmartcardCertificate);
|
||||
if (!scCert->certificate)
|
||||
{
|
||||
WLog_ERR(TAG, "unable to read smartcard certificate");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (!treat_sc_cert(scCert))
|
||||
{
|
||||
WLog_ERR(TAG, "unable to treat smartcard certificate");
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (ConvertToUnicode(CP_UTF8, 0, "FreeRDP Emulator", -1, &scCert->reader, 0) < 0)
|
||||
goto out_error;
|
||||
|
||||
scCert->containerName = strdup("Private Key 00");
|
||||
if (!scCert->containerName)
|
||||
goto out_error;
|
||||
|
||||
*retCount = 1;
|
||||
return TRUE;
|
||||
|
||||
out_error:
|
||||
smartcardCert_Free(scCert);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL smartcard_enumerateCerts(rdpSettings* settings, SmartcardCert* scCert, DWORD count,
|
||||
DWORD* retCount)
|
||||
{
|
||||
BOOL ret;
|
||||
LPWSTR csp;
|
||||
const char* asciiCsp = settings->CspName ? settings->CspName : MS_SCARD_PROV_A;
|
||||
|
||||
if (settings->SmartcardEmulation)
|
||||
return smartcard_sw_enumerateCerts(settings, scCert, count, retCount);
|
||||
|
||||
if (ConvertToUnicode(CP_UTF8, 0, asciiCsp, -1, &csp, 0) <= 0)
|
||||
{
|
||||
WLog_ERR(TAG, "error while converting CSP to WCHAR");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = smartcard_hw_enumerateCerts(settings, csp, settings->ReaderName, settings->Username,
|
||||
scCert, count, retCount);
|
||||
free(csp);
|
||||
return ret;
|
||||
}
|
||||
47
libfreerdp/core/smartcardlogon.h
Normal file
47
libfreerdp/core/smartcardlogon.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Logging in with smartcards
|
||||
*
|
||||
* Copyright 2022 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 LIBFREERDP_CORE_SMARTCARDLOGON_H
|
||||
#define LIBFREERDP_CORE_SMARTCARDLOGON_H
|
||||
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/crypto/crypto.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPWSTR reader;
|
||||
CryptoCert certificate;
|
||||
char* pkinitArgs;
|
||||
UINT32 slotId;
|
||||
char* containerName;
|
||||
char* upn;
|
||||
char* userHint;
|
||||
char* domainHint;
|
||||
char* subject;
|
||||
char* issuer;
|
||||
BYTE atr[256];
|
||||
DWORD atrLength;
|
||||
BYTE sha1Hash[20];
|
||||
} SmartcardCert;
|
||||
|
||||
void smartcardCert_Free(SmartcardCert* scCert);
|
||||
|
||||
BOOL smartcard_enumerateCerts(rdpSettings* settings, SmartcardCert* scCert, DWORD count,
|
||||
DWORD* retCount);
|
||||
|
||||
#endif /* LIBFREERDP_CORE_SMARTCARDLOGON_H */
|
||||
@@ -89,6 +89,7 @@ static const size_t bool_list_indices[] = {
|
||||
FreeRDP_IgnoreCertificate,
|
||||
FreeRDP_JpegCodec,
|
||||
FreeRDP_ListMonitors,
|
||||
FreeRDP_ListSmartcards,
|
||||
FreeRDP_LocalConnection,
|
||||
FreeRDP_LogonErrors,
|
||||
FreeRDP_LogonNotify,
|
||||
@@ -232,6 +233,7 @@ static const size_t uint32_list_indices[] = {
|
||||
FreeRDP_GlyphSupportLevel,
|
||||
FreeRDP_JpegCodecId,
|
||||
FreeRDP_JpegQuality,
|
||||
FreeRDP_KeySpec,
|
||||
FreeRDP_KeyboardCodePage,
|
||||
FreeRDP_KeyboardFunctionKey,
|
||||
FreeRDP_KeyboardHook,
|
||||
@@ -322,6 +324,7 @@ static const size_t string_list_indices[] = {
|
||||
FreeRDP_AlternateShell,
|
||||
FreeRDP_AssistanceFile,
|
||||
FreeRDP_AuthenticationServiceClass,
|
||||
FreeRDP_CardName,
|
||||
FreeRDP_CertificateAcceptedFingerprints,
|
||||
FreeRDP_CertificateContent,
|
||||
FreeRDP_CertificateFile,
|
||||
@@ -333,6 +336,8 @@ static const size_t string_list_indices[] = {
|
||||
FreeRDP_ComputerName,
|
||||
FreeRDP_ConfigPath,
|
||||
FreeRDP_ConnectionFile,
|
||||
FreeRDP_ContainerName,
|
||||
FreeRDP_CspName,
|
||||
FreeRDP_CurrentPath,
|
||||
FreeRDP_Domain,
|
||||
FreeRDP_DrivesToRedirect,
|
||||
@@ -347,11 +352,17 @@ static const size_t string_list_indices[] = {
|
||||
FreeRDP_HomePath,
|
||||
FreeRDP_ImeFileName,
|
||||
FreeRDP_KerberosKdc,
|
||||
FreeRDP_KerberosLifeTime,
|
||||
FreeRDP_KerberosRealm,
|
||||
FreeRDP_KerberosRenewableLifeTime,
|
||||
FreeRDP_KerberosStartTime,
|
||||
FreeRDP_KeyboardRemappingList,
|
||||
FreeRDP_NtlmSamFile,
|
||||
FreeRDP_Password,
|
||||
FreeRDP_PasswordHash,
|
||||
FreeRDP_Pin,
|
||||
FreeRDP_Pkcs11Module,
|
||||
FreeRDP_PkinitAnchors,
|
||||
FreeRDP_PlayRemoteFxFile,
|
||||
FreeRDP_PreconnectionBlob,
|
||||
FreeRDP_PrivateKeyContent,
|
||||
@@ -362,6 +373,7 @@ static const size_t string_list_indices[] = {
|
||||
FreeRDP_RDP2TCPArgs,
|
||||
FreeRDP_RdpKeyContent,
|
||||
FreeRDP_RdpKeyFile,
|
||||
FreeRDP_ReaderName,
|
||||
FreeRDP_RedirectionAcceptedCert,
|
||||
FreeRDP_RedirectionDomain,
|
||||
FreeRDP_RedirectionTargetFQDN,
|
||||
@@ -381,8 +393,10 @@ static const size_t string_list_indices[] = {
|
||||
FreeRDP_ServerHostname,
|
||||
FreeRDP_ShellWorkingDirectory,
|
||||
FreeRDP_SmartcardCertificate,
|
||||
FreeRDP_SmartcardCertificateFile,
|
||||
FreeRDP_SmartcardPin,
|
||||
FreeRDP_SmartcardPrivateKey,
|
||||
FreeRDP_SmartcardPrivateKeyFile,
|
||||
FreeRDP_TargetNetAddress,
|
||||
FreeRDP_TransportDumpFile,
|
||||
FreeRDP_Username,
|
||||
|
||||
@@ -41,6 +41,23 @@ CryptoCert crypto_cert_read(const BYTE* data, UINT32 length)
|
||||
return cert;
|
||||
}
|
||||
|
||||
CryptoCert crypto_cert_pem_read(const char* data)
|
||||
{
|
||||
CryptoCert cert = malloc(sizeof(*cert));
|
||||
|
||||
if (!cert)
|
||||
return NULL;
|
||||
|
||||
cert->px509 = crypto_cert_from_pem(data, strlen(data), FALSE);
|
||||
if (!cert->px509)
|
||||
{
|
||||
free(cert);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cert;
|
||||
}
|
||||
|
||||
void crypto_cert_free(CryptoCert cert)
|
||||
{
|
||||
if (cert == NULL)
|
||||
|
||||
@@ -28,6 +28,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
smartcard_operations.c
|
||||
smartcard_pack.c
|
||||
smartcard_call.c
|
||||
smartcard_cli.c
|
||||
stopwatch.c)
|
||||
|
||||
freerdp_module_add(${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
50
libfreerdp/utils/smartcard_cli.c
Normal file
50
libfreerdp/utils/smartcard_cli.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Smartcard client functions
|
||||
*
|
||||
* Copyright 2021 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.
|
||||
*/
|
||||
#include <freerdp/utils/smartcard_cli.h>
|
||||
#include "../core/smartcardlogon.h"
|
||||
|
||||
BOOL freerdp_smartcard_list(rdpSettings* settings)
|
||||
{
|
||||
SmartcardCert certs[64] = { 0 };
|
||||
DWORD i, count;
|
||||
|
||||
if (!smartcard_enumerateCerts(settings, certs, 64, &count))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
char readerName[256] = { 0 };
|
||||
|
||||
printf("%d: %s\n", i, certs[i].subject);
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, certs[i].reader, -1, readerName, sizeof(readerName),
|
||||
NULL, NULL) > 0)
|
||||
printf("\t* reader: %s\n", readerName);
|
||||
#ifndef _WIN32
|
||||
printf("\t* slotId: %" PRIu32 "\n", certs[i].slotId);
|
||||
printf("\t* pkinitArgs: %s\n", certs[i].pkinitArgs);
|
||||
#endif
|
||||
printf("\t* containerName: %s\n", certs[i].containerName);
|
||||
if (certs[i].upn)
|
||||
printf("\t* UPN: %s\n", certs[i].upn);
|
||||
|
||||
smartcardCert_Free(&certs[i]);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
57
winpr/include/winpr/cred.h
Normal file
57
winpr/include/winpr/cred.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* Windows credentials
|
||||
*
|
||||
* Copyright 2022 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_CRED_H_
|
||||
#define WINPR_CRED_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <wincred.h>
|
||||
#else
|
||||
|
||||
#define CERT_HASH_LENGTH 20
|
||||
|
||||
typedef enum _CRED_MARSHAL_TYPE
|
||||
{
|
||||
CertCredential,
|
||||
UsernameTargetCredential,
|
||||
BinaryBlobCredential,
|
||||
UsernameForPackedCredentials,
|
||||
BinaryBlobForSystem
|
||||
} CRED_MARSHAL_TYPE,
|
||||
*PCRED_MARSHAL_TYPE;
|
||||
|
||||
typedef struct _CERT_CREDENTIAL_INFO
|
||||
{
|
||||
ULONG cbSize;
|
||||
UCHAR rgbHashOfCert[CERT_HASH_LENGTH];
|
||||
} CERT_CREDENTIAL_INFO, *PCERT_CREDENTIAL_INFO;
|
||||
|
||||
BOOL CredMarshalCredentialA(CRED_MARSHAL_TYPE CredType, PVOID Credential,
|
||||
LPSTR* MarshaledCredential);
|
||||
BOOL CredMarshalCredentialW(CRED_MARSHAL_TYPE CredType, PVOID Credential,
|
||||
LPWSTR* MarshaledCredential);
|
||||
|
||||
#ifdef UNICODE
|
||||
#define CredMarshalCredential CredMarshalCredentialW
|
||||
#else
|
||||
#define CredMarshalCredential CredMarshalCredentialA
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* WINPR_CRED_H_ */
|
||||
@@ -157,23 +157,27 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
|
||||
NCryptProviderName** ppProviderList, DWORD dwFlags);
|
||||
WINPR_API SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
|
||||
NCryptProviderName** ppProviderList,
|
||||
DWORD dwFlags);
|
||||
|
||||
SECURITY_STATUS NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE* phProvider,
|
||||
LPCWSTR pszProviderName, DWORD dwFlags);
|
||||
WINPR_API SECURITY_STATUS NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE* phProvider,
|
||||
LPCWSTR pszProviderName, DWORD dwFlags);
|
||||
|
||||
SECURITY_STATUS NCryptEnumKeys(NCRYPT_PROV_HANDLE hProvider, LPCWSTR pszScope,
|
||||
NCryptKeyName** ppKeyName, PVOID* ppEnumState, DWORD dwFlags);
|
||||
WINPR_API SECURITY_STATUS NCryptEnumKeys(NCRYPT_PROV_HANDLE hProvider, LPCWSTR pszScope,
|
||||
NCryptKeyName** ppKeyName, PVOID* ppEnumState,
|
||||
DWORD dwFlags);
|
||||
|
||||
SECURITY_STATUS NCryptOpenKey(NCRYPT_PROV_HANDLE hProvider, NCRYPT_KEY_HANDLE* phKey,
|
||||
LPCWSTR pszKeyName, DWORD dwLegacyKeySpec, DWORD dwFlags);
|
||||
WINPR_API SECURITY_STATUS NCryptOpenKey(NCRYPT_PROV_HANDLE hProvider, NCRYPT_KEY_HANDLE* phKey,
|
||||
LPCWSTR pszKeyName, DWORD dwLegacyKeySpec,
|
||||
DWORD dwFlags);
|
||||
|
||||
SECURITY_STATUS NCryptGetProperty(NCRYPT_HANDLE hObject, LPCWSTR pszProperty, PBYTE pbOutput,
|
||||
DWORD cbOutput, DWORD* pcbResult, DWORD dwFlags);
|
||||
WINPR_API SECURITY_STATUS NCryptGetProperty(NCRYPT_HANDLE hObject, LPCWSTR pszProperty,
|
||||
PBYTE pbOutput, DWORD cbOutput, DWORD* pcbResult,
|
||||
DWORD dwFlags);
|
||||
|
||||
SECURITY_STATUS NCryptFreeObject(NCRYPT_HANDLE hObject);
|
||||
SECURITY_STATUS NCryptFreeBuffer(PVOID pvInput);
|
||||
WINPR_API SECURITY_STATUS NCryptFreeObject(NCRYPT_HANDLE hObject);
|
||||
WINPR_API SECURITY_STATUS NCryptFreeBuffer(PVOID pvInput);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
#include <sspi.h>
|
||||
#include <security.h>
|
||||
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
|
||||
#ifndef SEC_ENTRY
|
||||
#define SEC_ENTRY
|
||||
#endif
|
||||
#endif /* SEC_ENTRY */
|
||||
|
||||
typedef CHAR SEC_CHAR;
|
||||
typedef WCHAR SEC_WCHAR;
|
||||
@@ -62,7 +62,7 @@ typedef SECURITY_INTEGER* PTimeStamp;
|
||||
#ifndef __SECSTATUS_DEFINED__
|
||||
typedef LONG SECURITY_STATUS;
|
||||
#define __SECSTATUS_DEFINED__
|
||||
#endif
|
||||
#endif /* __SECSTATUS_DEFINED__ */
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
@@ -96,9 +96,9 @@ typedef SecPkgInfoW* PSecPkgInfoW;
|
||||
#else
|
||||
#define SecPkgInfo SecPkgInfoA
|
||||
#define PSecPkgInfo PSecPkgInfoA
|
||||
#endif
|
||||
#endif /* UNICODE */
|
||||
|
||||
#endif
|
||||
#endif /* !defined(_WIN32) || defined(_UWP) */
|
||||
|
||||
#define NTLM_SSP_NAME _T("NTLM")
|
||||
#define KERBEROS_SSP_NAME _T("Kerberos")
|
||||
@@ -217,7 +217,7 @@ typedef SecPkgInfoW* PSecPkgInfoW;
|
||||
#define SEC_I_SIGNATURE_NEEDED (SECURITY_STATUS)0x0009035CL
|
||||
#define SEC_I_NO_RENEGOTIATION (SECURITY_STATUS)0x00090360L
|
||||
|
||||
#endif
|
||||
#endif /* _WINERROR_ */
|
||||
|
||||
/* ============== some definitions missing in mingw ========================*/
|
||||
#ifndef SEC_E_INVALID_PARAMETER
|
||||
@@ -482,7 +482,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW;
|
||||
#define PSecPkgCredentials_Names PSecPkgCredentials_NamesA
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* !defined(_WIN32) || defined(_UWP) */
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
#if !defined(__MINGW32__)
|
||||
@@ -601,6 +601,17 @@ typedef struct
|
||||
#define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1
|
||||
#define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* armorCache;
|
||||
char* pkinitX509Anchors;
|
||||
char* pkinitX509Identity;
|
||||
BOOL withPac;
|
||||
INT32 startTime;
|
||||
INT32 lifeTime;
|
||||
BYTE certSha1[20];
|
||||
} SEC_WINPR_KERBEROS_SETTINGS;
|
||||
|
||||
#if !defined(_WIN32) || defined(_UWP)
|
||||
|
||||
#if defined(__clang__)
|
||||
@@ -649,6 +660,42 @@ typedef struct
|
||||
|
||||
#endif /* _AUTH_IDENTITY_DEFINED */
|
||||
|
||||
#ifndef SEC_WINNT_AUTH_IDENTITY_VERSION
|
||||
#define SEC_WINNT_AUTH_IDENTITY_VERSION 0x200
|
||||
|
||||
typedef struct _SEC_WINNT_AUTH_IDENTITY_EXW
|
||||
{
|
||||
UINT32 Version;
|
||||
UINT32 Length;
|
||||
UINT16* User;
|
||||
UINT32 UserLength;
|
||||
UINT16* Domain;
|
||||
UINT32 DomainLength;
|
||||
UINT16* Password;
|
||||
UINT32 PasswordLength;
|
||||
UINT32 Flags;
|
||||
BYTE* PackageList;
|
||||
UINT32 PackageListLength;
|
||||
} SEC_WINNT_AUTH_IDENTITY_EXW, *PSEC_WINNT_AUTH_IDENTITY_EXW;
|
||||
|
||||
typedef struct _SEC_WINNT_AUTH_IDENTITY_EXA
|
||||
{
|
||||
UINT32 Version;
|
||||
UINT32 Length;
|
||||
BYTE* User;
|
||||
UINT32 UserLength;
|
||||
BYTE* Domain;
|
||||
UINT32 DomainLength;
|
||||
BYTE* Password;
|
||||
UINT32 PasswordLength;
|
||||
UINT32 Flags;
|
||||
BYTE* PackageList;
|
||||
UINT32 PackageListLength;
|
||||
} SEC_WINNT_AUTH_IDENTITY_EXA, *PSEC_WINNT_AUTH_IDENTITY_EXA;
|
||||
|
||||
#endif /* SEC_WINNT_AUTH_IDENTITY_VERSION */
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
@@ -672,7 +719,19 @@ typedef CtxtHandle* PCtxtHandle;
|
||||
((((PSecHandle)(x))->dwLower != ((ULONG_PTR)((INT_PTR)-1))) && \
|
||||
(((PSecHandle)(x))->dwUpper != ((ULONG_PTR)((INT_PTR)-1))))
|
||||
|
||||
#endif
|
||||
#endif /* !defined(_WIN32) || defined(_UWP) */
|
||||
|
||||
typedef struct _SEC_WINNT_AUTH_IDENTITY_WINPRA
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_EXA identityEx;
|
||||
SEC_WINPR_KERBEROS_SETTINGS* kerberosSettings;
|
||||
} SEC_WINNT_AUTH_IDENTITY_WINPRA, *PSEC_WINNT_AUTH_IDENTITY_WINPRA;
|
||||
|
||||
typedef struct _SEC_WINNT_AUTH_IDENTITY_WINPRW
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_EXW identityEx;
|
||||
SEC_WINPR_KERBEROS_SETTINGS* kerberosSettings;
|
||||
} SEC_WINNT_AUTH_IDENTITY_WINPRW, *PSEC_WINNT_AUTH_IDENTITY_WINPRW;
|
||||
|
||||
#define SECBUFFER_VERSION 0
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ winpr_module_add(
|
||||
ncrypt_pkcs11.c
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
winpr_library_add_public(ncrypt)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
@@ -84,11 +84,13 @@ SECURITY_STATUS winpr_NCryptDefault_dtor(NCRYPT_HANDLE handle)
|
||||
SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
|
||||
NCryptProviderName** ppProviderList, DWORD dwFlags)
|
||||
{
|
||||
static const WCHAR emptyComment[] = { 0 };
|
||||
NCryptProviderName* ret;
|
||||
size_t stringAllocSize = 0;
|
||||
#ifdef WITH_PKCS11
|
||||
LPWSTR strPtr;
|
||||
static const WCHAR emptyComment[] = { 0 };
|
||||
size_t copyAmount;
|
||||
#endif
|
||||
|
||||
*wProviderCount = 0;
|
||||
*ppProviderList = NULL;
|
||||
@@ -106,9 +108,10 @@ SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
|
||||
if (!ret)
|
||||
return NTE_NO_MEMORY;
|
||||
|
||||
strPtr = (LPWSTR)(ret + *wProviderCount);
|
||||
|
||||
#ifdef WITH_PKCS11
|
||||
strPtr = (LPWSTR)(ret + *wProviderCount);
|
||||
|
||||
ret->pszName = strPtr;
|
||||
copyAmount = (_wcslen(MS_SCARD_PROV) + 1) * 2;
|
||||
memcpy(strPtr, MS_SCARD_PROV, copyAmount);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/crt.h>
|
||||
@@ -231,7 +233,26 @@ static int kerberos_SetContextServicePrincipalNameA(KRB_CONTEXT* context,
|
||||
}
|
||||
|
||||
#ifdef WITH_GSSAPI
|
||||
static krb5_error_code acquire_cred(krb5_context ctx, krb5_principal client, const char* password)
|
||||
|
||||
static krb5_error_code krb5_prompter(krb5_context context, void* data, const char* name,
|
||||
const char* banner, int num_prompts, krb5_prompt prompts[])
|
||||
{
|
||||
int i;
|
||||
krb5_prompt_type* ptypes = krb5_get_prompt_types(context);
|
||||
|
||||
for (i = 0; i < num_prompts; i++)
|
||||
{
|
||||
if (ptypes && ptypes[i] == KRB5_PROMPT_TYPE_PREAUTH)
|
||||
{
|
||||
prompts[i].reply->data = strdup((const char*)data);
|
||||
prompts[i].reply->length = strlen((const char*)data);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code acquire_cred(krb5_context ctx, SEC_WINPR_KERBEROS_SETTINGS* optionsBlock,
|
||||
krb5_principal client, const char* password)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_creds creds;
|
||||
@@ -264,6 +285,21 @@ static krb5_error_code acquire_cred(krb5_context ctx, krb5_principal client, con
|
||||
/* Set default options */
|
||||
krb5_get_init_creds_opt_set_forwardable(options, 0);
|
||||
krb5_get_init_creds_opt_set_proxiable(options, 0);
|
||||
|
||||
if (optionsBlock && optionsBlock->withPac)
|
||||
krb5_get_init_creds_opt_set_pac_request(ctx, options, TRUE);
|
||||
|
||||
if (optionsBlock && optionsBlock->armorCache)
|
||||
krb5_get_init_creds_opt_set_fast_ccache_name(ctx, options, optionsBlock->armorCache);
|
||||
|
||||
if (optionsBlock && optionsBlock->pkinitX509Identity)
|
||||
krb5_get_init_creds_opt_set_pa(ctx, options, "X509_user_identity",
|
||||
optionsBlock->pkinitX509Identity);
|
||||
|
||||
if (optionsBlock && optionsBlock->pkinitX509Anchors)
|
||||
krb5_get_init_creds_opt_set_pa(ctx, options, "X509_anchors",
|
||||
optionsBlock->pkinitX509Anchors);
|
||||
|
||||
#ifdef WITH_GSSAPI_MIT
|
||||
|
||||
/* for MIT we specify ccache output using an option */
|
||||
@@ -275,7 +311,8 @@ static krb5_error_code acquire_cred(krb5_context ctx, krb5_principal client, con
|
||||
|
||||
#endif
|
||||
|
||||
if ((ret = krb5_init_creds_init(ctx, client, NULL, NULL, starttime, options, &init_ctx)))
|
||||
if ((ret = krb5_init_creds_init(ctx, client, krb5_prompter, (void*)password, starttime, options,
|
||||
&init_ctx)))
|
||||
{
|
||||
WLog_ERR(TAG, "error krb5_init_creds_init failed");
|
||||
goto cleanup;
|
||||
@@ -332,7 +369,8 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, size_t password_len)
|
||||
static int init_creds(SEC_WINPR_KERBEROS_SETTINGS* options, LPCWSTR username, size_t username_len,
|
||||
LPCWSTR domain, size_t domain_len, LPCWSTR password, size_t password_len)
|
||||
{
|
||||
krb5_error_code ret = 0;
|
||||
krb5_context ctx = NULL;
|
||||
@@ -347,6 +385,8 @@ static int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, s
|
||||
size_t lrealm_len = 0;
|
||||
size_t lusername_len = 0;
|
||||
int status = 0;
|
||||
BOOL isDefaultRealm = FALSE;
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, username, username_len, &lusername, 0, NULL, NULL);
|
||||
|
||||
if (status <= 0)
|
||||
@@ -356,7 +396,6 @@ static int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, s
|
||||
}
|
||||
|
||||
status = ConvertFromUnicode(CP_UTF8, 0, password, password_len, &lpassword, 0, NULL, NULL);
|
||||
|
||||
if (status <= 0)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to convert password");
|
||||
@@ -372,12 +411,29 @@ static int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, s
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = krb5_get_default_realm(ctx, &lrealm);
|
||||
|
||||
if (ret)
|
||||
if (domain && domain_len)
|
||||
{
|
||||
WLog_WARN(TAG, "could not get Kerberos default realm");
|
||||
goto cleanup;
|
||||
char* tmp;
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, domain, domain_len, &lrealm, 0, NULL, NULL) <= 0)
|
||||
{
|
||||
WLog_ERR(TAG, "error: converting domain");
|
||||
}
|
||||
|
||||
/* convert to upper case */
|
||||
for (tmp = lrealm; *tmp; tmp++)
|
||||
*tmp = toupper(*tmp);
|
||||
|
||||
isDefaultRealm = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = krb5_get_default_realm(ctx, &lrealm);
|
||||
if (ret)
|
||||
{
|
||||
WLog_WARN(TAG, "could not get Kerberos default realm");
|
||||
goto cleanup;
|
||||
}
|
||||
isDefaultRealm = TRUE;
|
||||
}
|
||||
|
||||
lrealm_len = strlen(lrealm);
|
||||
@@ -411,7 +467,7 @@ static int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, s
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = acquire_cred(ctx, principal, lpassword);
|
||||
ret = acquire_cred(ctx, options, principal, lpassword);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
@@ -427,7 +483,12 @@ cleanup:
|
||||
free(krb_name);
|
||||
|
||||
if (lrealm)
|
||||
krb5_free_default_realm(ctx, lrealm);
|
||||
{
|
||||
if (isDefaultRealm)
|
||||
krb5_free_default_realm(ctx, lrealm);
|
||||
else
|
||||
free(lrealm);
|
||||
}
|
||||
|
||||
if (principal)
|
||||
krb5_free_principal(ctx, principal);
|
||||
@@ -497,10 +558,11 @@ static SECURITY_STATUS SEC_ENTRY kerberos_InitializeSecurityContextA(
|
||||
* If we use smartcard-logon, the credentials have already
|
||||
* been acquired by pkinit process. If not, returned error previously.
|
||||
*/
|
||||
if (init_creds(context->credentials->identity.User,
|
||||
context->credentials->identity.UserLength,
|
||||
context->credentials->identity.Password,
|
||||
context->credentials->identity.PasswordLength))
|
||||
SSPI_CREDENTIALS* credentials = context->credentials;
|
||||
if (init_creds(credentials->kerbSettings, credentials->identity.User,
|
||||
credentials->identity.UserLength, credentials->identity.Domain,
|
||||
credentials->identity.DomainLength, credentials->identity.Password,
|
||||
credentials->identity.PasswordLength))
|
||||
return SEC_E_NO_CREDENTIALS;
|
||||
|
||||
WLog_INFO(TAG, "Authenticated to Kerberos v5 via login/password");
|
||||
|
||||
@@ -486,7 +486,6 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(
|
||||
PTimeStamp ptsExpiry)
|
||||
{
|
||||
SSPI_CREDENTIALS* credentials;
|
||||
SEC_WINNT_AUTH_IDENTITY* identity;
|
||||
|
||||
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && (fCredentialUse != SECPKG_CRED_INBOUND) &&
|
||||
(fCredentialUse != SECPKG_CRED_BOTH))
|
||||
@@ -495,17 +494,50 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(
|
||||
}
|
||||
|
||||
credentials = sspi_CredentialsNew();
|
||||
|
||||
if (!credentials)
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
|
||||
credentials->fCredentialUse = fCredentialUse;
|
||||
credentials->pGetKeyFn = pGetKeyFn;
|
||||
credentials->pvGetKeyArgument = pvGetKeyArgument;
|
||||
identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
|
||||
|
||||
if (identity)
|
||||
sspi_CopyAuthIdentity(&(credentials->identity), identity);
|
||||
if (pAuthData)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_EXW* identityEx = (SEC_WINNT_AUTH_IDENTITY_EXW*)pAuthData;
|
||||
BOOL treated = FALSE;
|
||||
|
||||
SEC_WINNT_AUTH_IDENTITY srcIdentity;
|
||||
if (identityEx->Version == SEC_WINNT_AUTH_IDENTITY_VERSION)
|
||||
{
|
||||
if (identityEx->Length >= sizeof(*identityEx))
|
||||
{
|
||||
srcIdentity.User = (UINT16*)identityEx->User;
|
||||
srcIdentity.UserLength = identityEx->UserLength;
|
||||
srcIdentity.Domain = (UINT16*)identityEx->Domain;
|
||||
srcIdentity.DomainLength = identityEx->DomainLength;
|
||||
srcIdentity.Password = (UINT16*)identityEx->Password;
|
||||
srcIdentity.PasswordLength = identityEx->PasswordLength;
|
||||
srcIdentity.Flags = identityEx->Flags;
|
||||
|
||||
if (!sspi_CopyAuthIdentity(&credentials->identity, &srcIdentity))
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
if (identityEx->Length == sizeof(SEC_WINNT_AUTH_IDENTITY_WINPRA))
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_WINPRW* identityWinpr =
|
||||
(SEC_WINNT_AUTH_IDENTITY_WINPRW*)pAuthData;
|
||||
credentials->kerbSettings = identityWinpr->kerberosSettings;
|
||||
}
|
||||
treated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!treated)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY* identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
|
||||
sspi_CopyAuthIdentity(&(credentials->identity), identity);
|
||||
}
|
||||
}
|
||||
|
||||
sspi_SecureHandleSetLowerPointer(phCredential, (void*)credentials);
|
||||
sspi_SecureHandleSetUpperPointer(phCredential, (void*)NEGO_SSP_NAME);
|
||||
@@ -518,7 +550,6 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(
|
||||
PTimeStamp ptsExpiry)
|
||||
{
|
||||
SSPI_CREDENTIALS* credentials;
|
||||
SEC_WINNT_AUTH_IDENTITY* identity;
|
||||
|
||||
if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && (fCredentialUse != SECPKG_CRED_INBOUND) &&
|
||||
(fCredentialUse != SECPKG_CRED_BOTH))
|
||||
@@ -534,10 +565,44 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(
|
||||
credentials->fCredentialUse = fCredentialUse;
|
||||
credentials->pGetKeyFn = pGetKeyFn;
|
||||
credentials->pvGetKeyArgument = pvGetKeyArgument;
|
||||
identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
|
||||
|
||||
if (identity)
|
||||
sspi_CopyAuthIdentity(&(credentials->identity), identity);
|
||||
if (pAuthData)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_EXA* identityEx = (SEC_WINNT_AUTH_IDENTITY_EXA*)pAuthData;
|
||||
BOOL treated = FALSE;
|
||||
|
||||
SEC_WINNT_AUTH_IDENTITY srcIdentity;
|
||||
if (identityEx->Version == SEC_WINNT_AUTH_IDENTITY_VERSION)
|
||||
{
|
||||
if (identityEx->Length >= sizeof(*identityEx))
|
||||
{
|
||||
srcIdentity.User = (UINT16*)identityEx->User;
|
||||
srcIdentity.UserLength = identityEx->UserLength;
|
||||
srcIdentity.Domain = (UINT16*)identityEx->Domain;
|
||||
srcIdentity.DomainLength = identityEx->DomainLength;
|
||||
srcIdentity.Password = (UINT16*)identityEx->Password;
|
||||
srcIdentity.PasswordLength = identityEx->PasswordLength;
|
||||
srcIdentity.Flags = identityEx->Flags;
|
||||
|
||||
if (!sspi_CopyAuthIdentity(&credentials->identity, &srcIdentity))
|
||||
return SEC_E_INSUFFICIENT_MEMORY;
|
||||
|
||||
if (identityEx->Length == sizeof(SEC_WINNT_AUTH_IDENTITY_WINPRA))
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY_WINPRA* identityWinpr =
|
||||
(SEC_WINNT_AUTH_IDENTITY_WINPRA*)pAuthData;
|
||||
credentials->kerbSettings = identityWinpr->kerberosSettings;
|
||||
}
|
||||
treated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!treated)
|
||||
{
|
||||
SEC_WINNT_AUTH_IDENTITY* identity = (SEC_WINNT_AUTH_IDENTITY*)pAuthData;
|
||||
sspi_CopyAuthIdentity(&(credentials->identity), identity);
|
||||
}
|
||||
}
|
||||
|
||||
sspi_SecureHandleSetLowerPointer(phCredential, (void*)credentials);
|
||||
sspi_SecureHandleSetUpperPointer(phCredential, (void*)NEGO_SSP_NAME);
|
||||
|
||||
@@ -28,14 +28,16 @@
|
||||
|
||||
#define SSPI_CREDENTIALS_HASH_LENGTH_OFFSET 512
|
||||
|
||||
typedef struct
|
||||
struct _SSPI_CREDENTIALS
|
||||
{
|
||||
DWORD flags;
|
||||
ULONG fCredentialUse;
|
||||
SEC_GET_KEY_FN pGetKeyFn;
|
||||
void* pvGetKeyArgument;
|
||||
SEC_WINNT_AUTH_IDENTITY identity;
|
||||
} SSPI_CREDENTIALS;
|
||||
SEC_WINPR_KERBEROS_SETTINGS* kerbSettings;
|
||||
};
|
||||
typedef struct _SSPI_CREDENTIALS SSPI_CREDENTIALS;
|
||||
|
||||
SSPI_CREDENTIALS* sspi_CredentialsNew(void);
|
||||
void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials);
|
||||
|
||||
Reference in New Issue
Block a user