Removed Smartcard files from settings

* Removed file names from settings
* Added temporary file creation for pkinit
This commit is contained in:
Armin Novak 2022-02-02 15:57:05 +01:00 committed by akallabeth
parent 649527ef8d
commit b3790d7454
9 changed files with 316 additions and 194 deletions

View File

@ -3354,9 +3354,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
const char* f = &cur[5];
if (!freerdp_settings_set_string(settings, FreeRDP_SmartcardCertificateFile,
f) ||
!read_pem_file(settings, FreeRDP_SmartcardCertificate, f))
if (!read_pem_file(settings, FreeRDP_SmartcardCertificate, f))
{
free(ptr.p);
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
@ -3365,9 +3363,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
else if (strncmp("key:", cur, 4) == 0)
{
const char* f = &cur[4];
if (!freerdp_settings_set_string(settings, FreeRDP_SmartcardPrivateKeyFile,
f) ||
!read_pem_file(settings, FreeRDP_SmartcardPrivateKey, f))
if (!read_pem_file(settings, FreeRDP_SmartcardPrivateKey, f))
{
free(ptr.p);
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

View File

@ -16,35 +16,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/assert.h>
#include <freerdp/utils/smartcard_cli.h>
#include "../../libfreerdp/core/smartcardlogon.h"
BOOL freerdp_smartcard_list(const rdpSettings* settings)
{
SmartcardCert certs[64] = { 0 };
SmartcardCerts* certs = NULL;
DWORD i, count;
if (!smartcard_enumerateCerts(settings, certs, 64, &count))
if (!smartcard_enumerateCerts(settings, &certs, &count))
return FALSE;
for (i = 0; i < count; i++)
{
const SmartcardCertInfo* info = smartcard_getCertInfo(certs, i);
char readerName[256] = { 0 };
printf("%d: %s\n", i, certs[i].subject);
WINPR_ASSERT(info);
if (WideCharToMultiByte(CP_UTF8, 0, certs[i].reader, -1, readerName, sizeof(readerName),
NULL, NULL) > 0)
printf("%d: %s\n", i, info->subject);
if (WideCharToMultiByte(CP_UTF8, 0, info->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);
printf("\t* slotId: %" PRIu32 "\n", info->slotId);
printf("\t* pkinitArgs: %s\n", info->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]);
printf("\t* containerName: %s\n", info->containerName);
if (info->upn)
printf("\t* UPN: %s\n", info->upn);
}
smartcardCerts_Free(certs);
return TRUE;
}

View File

@ -663,16 +663,14 @@ 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_Pkcs11Module (1289)
#define FreeRDP_Pin (1290)
#define FreeRDP_KeySpec (1291)
#define FreeRDP_CardName (1292)
#define FreeRDP_ReaderName (1293)
#define FreeRDP_ContainerName (1294)
#define FreeRDP_CspName (1295)
#define FreeRDP_PkinitAnchors (1296)
#define FreeRDP_KerberosKdc (1344)
#define FreeRDP_KerberosRealm (1345)
#define FreeRDP_KerberosStartTime (1346)
@ -1163,17 +1161,15 @@ struct rdp_settings
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 */
UINT64 padding1344[1344 - 1299]; /* 1299 */
ALIGN64 char* Pkcs11Module; /* 1289 */
ALIGN64 char* Pin; /* 1290 */
ALIGN64 UINT32 KeySpec; /* 1291 */
ALIGN64 char* CardName; /* 1292 */
ALIGN64 char* ReaderName; /* 1293 */
ALIGN64 char* ContainerName; /* 1294 */
ALIGN64 char* CspName; /* 1295 */
ALIGN64 char* PkinitAnchors; /* 1296 */
UINT64 padding1344[1344 - 1297]; /* 1297 */
/* Kerberos Authentication */
ALIGN64 char* KerberosKdc; /* 1344 */

View File

@ -2554,18 +2554,12 @@ 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;
@ -2818,18 +2812,12 @@ 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;
@ -3092,18 +3080,12 @@ 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);

View File

@ -383,10 +383,8 @@ 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" },

View File

@ -538,9 +538,9 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
{
#define MAX_SC_CERTS 64
SmartcardCert certs[MAX_SC_CERTS];
DWORD count, i = 0;
SmartcardCerts* certs = NULL;
const SmartcardCertInfo* info = NULL;
DWORD count;
rdpSettings* settings = nla->settings;
SEC_WINPR_KERBEROS_SETTINGS* kerbSettings = &nla->kerberosSettings;
BOOL ret = FALSE;
@ -564,68 +564,71 @@ static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
}
}
if (!smartcard_enumerateCerts(settings, certs, MAX_SC_CERTS, &count))
if (!smartcard_enumerateCerts(settings, &certs, &count))
{
WLog_ERR(TAG, "unable to list smartcard certificates");
return FALSE;
}
if (!count)
if (count < 1)
{
WLog_ERR(TAG, "no smartcard certificates found");
return FALSE;
goto out;
}
if (count != 1)
goto setup_pin;
info = smartcard_getCertInfo(certs, 0);
if (!info)
goto out;
/*
* just one result let's try to fill missing parameters
*/
if (!settings->Username && certs[0].userHint)
if (!settings->Username && info->userHint)
{
if (!freerdp_settings_set_string(settings, FreeRDP_Username, certs[0].userHint))
if (!freerdp_settings_set_string(settings, FreeRDP_Username, info->userHint))
{
WLog_ERR(TAG, "unable to copy certificate username");
goto out;
}
}
if (!settings->Domain && certs[0].domainHint)
if (!settings->Domain && info->domainHint)
{
if (!freerdp_settings_set_string(settings, FreeRDP_Domain, certs[0].domainHint))
if (!freerdp_settings_set_string(settings, FreeRDP_Domain, info->domainHint))
{
WLog_ERR(TAG, "unable to copy certificate domain");
goto out;
}
}
if (!settings->ReaderName && certs[0].reader)
if (!settings->ReaderName && info->reader)
{
if (ConvertFromUnicode(CP_UTF8, 0, certs[0].reader, -1, &settings->ReaderName, 0, NULL,
NULL) < 0)
if (ConvertFromUnicode(CP_UTF8, 0, info->reader, -1, &settings->ReaderName, 0, NULL, NULL) <
0)
{
WLog_ERR(TAG, "unable to copy reader name");
goto out;
}
}
if (!settings->ContainerName && certs[0].containerName)
if (!settings->ContainerName && info->containerName)
{
if (!freerdp_settings_set_string(settings, FreeRDP_ContainerName, certs[0].containerName))
if (!freerdp_settings_set_string(settings, FreeRDP_ContainerName, info->containerName))
{
WLog_ERR(TAG, "unable to copy container name");
goto out;
}
}
memcpy(nla->kerberosSettings.certSha1, certs[0].sha1Hash,
sizeof(nla->kerberosSettings.certSha1));
memcpy(nla->kerberosSettings.certSha1, info->sha1Hash, sizeof(nla->kerberosSettings.certSha1));
#ifndef _WIN32
if (certs[0].pkinitArgs)
if (info->pkinitArgs)
{
kerbSettings->pkinitX509Identity = strdup(certs[0].pkinitArgs);
kerbSettings->pkinitX509Identity = _strdup(info->pkinitArgs);
if (!kerbSettings->pkinitX509Identity)
{
WLog_ERR(TAG, "unable to copy pkinitArgs");
@ -669,8 +672,7 @@ setup_pin:
ret = TRUE;
out:
for (i = 0; i < count; i++)
smartcardCert_Free(&certs[i]);
smartcardCerts_Free(certs);
return ret;
}
@ -1995,8 +1997,6 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
s = Stream_StaticInit(&staticRetStream, (BYTE*)nla->tsCredentials.pvBuffer, length);
ber_write_nla_TSCredentials(s, &cr);
ret = TRUE;
printf("creds=%s\n", winpr_BinToHexString((BYTE*)nla->tsCredentials.pvBuffer, length, TRUE));
out:
Stream_Free(credsContentStream, TRUE);
return ret;

View File

@ -29,6 +29,7 @@
#include <winpr/wlog.h>
#include <winpr/smartcard.h>
#include <winpr/crypto.h>
#include <winpr/path.h>
#include <freerdp/log.h>
@ -36,6 +37,19 @@
#define TAG FREERDP_TAG("smartcardlogon")
typedef struct
{
SmartcardCertInfo info;
char* certPath;
char* keyPath;
} SmartcardCertInfoPrivate;
struct sSmartCardCerts
{
size_t count;
SmartcardCertInfoPrivate* certs;
};
static BOOL getAtr(LPWSTR readerName, BYTE* atr, DWORD* atrLen)
{
WCHAR atrName[256];
@ -77,8 +91,12 @@ out_connect:
return ret;
}
void smartcardCert_Free(SmartcardCert* scCert)
static void smartcardCertInfo_Free(SmartcardCertInfo* scCert)
{
const SmartcardCertInfo empty = { 0 };
if (!scCert)
return;
free(scCert->reader);
crypto_cert_free(scCert->certificate);
free(scCert->pkinitArgs);
@ -89,10 +107,62 @@ void smartcardCert_Free(SmartcardCert* scCert)
free(scCert->subject);
free(scCert->issuer);
ZeroMemory(scCert, sizeof(*scCert));
*scCert = empty;
}
static BOOL treat_sc_cert(SmartcardCert* scCert)
static void delete_file(char* path)
{
WCHAR* wpath = NULL;
if (!path)
return;
/* Overwrite data in files before deletion */
{
FILE* fp = winpr_fopen(path, "r+");
if (fp)
{
INT64 x, size = 0;
int rs = _fseeki64(fp, 0, SEEK_END);
if (rs == 0)
size = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
for (x = 0; x < size; x++)
fputc(0, fp);
fclose(fp);
}
}
ConvertToUnicode(CP_UTF8, 0, path, -1, &wpath, 0);
DeleteFileW(wpath);
free(wpath);
free(path);
}
static void smartcardCertInfoPrivate_Free(SmartcardCertInfoPrivate* scCert)
{
const SmartcardCertInfoPrivate empty = { 0 };
if (!scCert)
return;
smartcardCertInfo_Free(&scCert->info);
delete_file(scCert->keyPath);
delete_file(scCert->certPath);
*scCert = empty;
}
void smartcardCerts_Free(SmartcardCerts* scCert)
{
size_t x;
if (!scCert)
return;
for (x = 0; x < scCert->count; x++)
smartcardCertInfoPrivate_Free(&scCert->certs[x]);
free(scCert);
}
static BOOL treat_sc_cert(SmartcardCertInfo* scCert)
{
scCert->upn = crypto_cert_get_upn(scCert->certificate->px509);
if (scCert->upn)
@ -106,7 +176,7 @@ static BOOL treat_sc_cert(SmartcardCert* scCert)
return FALSE;
}
userLen = (atPos - scCert->upn);
userLen = (size_t)(atPos - scCert->upn);
scCert->userHint = malloc(userLen + 1);
scCert->domainHint = strdup(atPos + 1);
@ -126,32 +196,47 @@ static BOOL treat_sc_cert(SmartcardCert* scCert)
return TRUE;
}
static int allocating_sprintf(char** dst, const char* fmt, ...)
{
int rc;
va_list ap;
WINPR_ASSERT(dst);
va_start(ap, fmt);
rc = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
{
char* tmp = realloc(*dst, rc + 1);
if (!tmp)
return -1;
*dst = tmp;
}
va_start(ap, fmt);
rc = vsnprintf(*dst, rc + 1, fmt, ap);
va_end(ap);
return rc;
}
#ifndef _WIN32
static BOOL build_pkinit_args(const rdpSettings* settings, SmartcardCert* scCert)
static BOOL build_pkinit_args(const rdpSettings* settings, SmartcardCertInfo* scCert)
{
/* pkinit args only under windows
* PKCS11:module_name=opensc-pkcs11.so
*/
size_t sz;
const char* pkModule = settings->Pkcs11Module ? settings->Pkcs11Module : "opensc-pkcs11.so";
sz = _snprintf(NULL, 0, "PKCS11:module_name=%s:slotid=%" PRIu16, pkModule,
(UINT16)scCert->slotId) +
1;
scCert->pkinitArgs = malloc(sz);
if (!scCert->pkinitArgs)
if (allocating_sprintf(&scCert->pkinitArgs, "PKCS11:module_name=%s:slotid=%" PRIu16, pkModule,
(UINT16)scCert->slotId) <= 0)
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(const rdpSettings* settings, LPCWSTR csp,
const char* reader, const char* userFilter,
SmartcardCert* scCert, DWORD count, DWORD* retCount)
SmartcardCerts** scCerts, DWORD* retCount)
{
BOOL ret = FALSE;
LPWSTR scope = NULL;
@ -159,6 +244,13 @@ static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp
NCRYPT_PROV_HANDLE provider;
NCryptKeyName* keyName = NULL;
SECURITY_STATUS status;
size_t count = 0;
SmartcardCerts* certs = NULL;
WINPR_ASSERT(settings);
WINPR_ASSERT(csp);
WINPR_ASSERT(scCerts);
WINPR_ASSERT(retCount);
if (reader)
{
@ -183,33 +275,42 @@ static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp
goto out;
}
*retCount = 0;
while ((*retCount < count) && (status = NCryptEnumKeys(provider, scope, &keyName, &enumState,
NCRYPT_SILENT_FLAG)) == ERROR_SUCCESS)
while ((status = NCryptEnumKeys(provider, scope, &keyName, &enumState, NCRYPT_SILENT_FLAG)) ==
ERROR_SUCCESS)
{
NCRYPT_KEY_HANDLE phKey;
NCRYPT_KEY_HANDLE phKey = 0;
PBYTE certBytes = NULL;
DWORD cbOutput;
SmartcardCertInfoPrivate* cert;
if (ConvertFromUnicode(CP_UTF8, 0, keyName->pszName, -1, &scCert->containerName, 0, NULL,
count++;
{
SmartcardCerts* tmp =
realloc(certs, sizeof(SmartcardCerts) + sizeof(SmartcardCertInfoPrivate) * (count));
if (!tmp)
goto out;
certs = tmp;
certs->count = count;
certs->certs = (SmartcardCertInfoPrivate*)(certs + 1);
}
cert = &certs->certs[count - 1];
if (ConvertFromUnicode(CP_UTF8, 0, keyName->pszName, -1, &cert->info.containerName, 0, NULL,
NULL) <= 0)
continue;
goto endofloop;
status = NCryptOpenKey(provider, &phKey, keyName->pszName, keyName->dwLegacyKeySpec,
keyName->dwFlags);
if (status != ERROR_SUCCESS)
{
smartcardCert_Free(scCert);
continue;
}
goto endofloop;
#ifndef _WIN32
status = NCryptGetProperty(phKey, NCRYPT_WINPR_SLOTID, (PBYTE)&scCert->slotId, 4, &cbOutput,
NCRYPT_SILENT_FLAG);
status = NCryptGetProperty(phKey, NCRYPT_WINPR_SLOTID, (PBYTE)&cert->info.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);
WLog_ERR(TAG, "unable to retrieve slotId for key %s", cert->info.containerName);
goto endofloop;
}
#endif /* _WIN32 */
@ -220,32 +321,28 @@ static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp
if (status != ERROR_SUCCESS)
{
WLog_ERR(TAG, "unable to retrieve reader's name length for key %s",
scCert->containerName);
smartcardCert_Free(scCert);
cert->info.containerName);
goto endofloop;
}
scCert->reader = calloc(1, cbOutput + 2);
if (!scCert->reader)
cert->info.reader = calloc(1, cbOutput + 2);
if (!cert->info.reader)
{
WLog_ERR(TAG, "unable to allocate reader's name for key %s", scCert->containerName);
smartcardCert_Free(scCert);
WLog_ERR(TAG, "unable to allocate reader's name for key %s", cert->info.containerName);
goto endofloop;
}
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, (PBYTE)scCert->reader,
status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, (PBYTE)cert->info.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);
WLog_ERR(TAG, "unable to retrieve reader's name for key %s", cert->info.containerName);
goto endofloop;
}
if (!getAtr(scCert->reader, scCert->atr, &scCert->atrLength))
if (!getAtr(cert->info.reader, cert->info.atr, &cert->info.atrLength))
{
WLog_ERR(TAG, "unable to retrieve card ATR for key %s", scCert->containerName);
smartcardCert_Free(scCert);
WLog_ERR(TAG, "unable to retrieve card ATR for key %s", cert->info.containerName);
goto endofloop;
}
@ -255,7 +352,6 @@ static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp
if (status != ERROR_SUCCESS)
{
/* can happen that key don't have certificates */
smartcardCert_Free(scCert);
goto endofloop;
}
@ -263,8 +359,7 @@ static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp
if (!certBytes)
{
WLog_ERR(TAG, "unable to allocate %d certBytes for key %s", cbOutput,
scCert->containerName);
smartcardCert_Free(scCert);
cert->info.containerName);
goto endofloop;
}
@ -272,59 +367,50 @@ static BOOL smartcard_hw_enumerateCerts(const rdpSettings* settings, LPCWSTR csp
&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);
WLog_ERR(TAG, "unable to retrieve certificate for key %s", cert->info.containerName);
goto endofloop;
}
if (!winpr_Digest(WINPR_MD_SHA1, certBytes, cbOutput, scCert->sha1Hash,
sizeof(scCert->sha1Hash)))
if (!winpr_Digest(WINPR_MD_SHA1, certBytes, cbOutput, cert->info.sha1Hash,
sizeof(cert->info.sha1Hash)))
{
WLog_ERR(TAG, "unable to compute certificate sha1 for key %s", scCert->containerName);
free(certBytes);
smartcardCert_Free(scCert);
WLog_ERR(TAG, "unable to compute certificate sha1 for key %s",
cert->info.containerName);
goto endofloop;
}
scCert->certificate = crypto_cert_read(certBytes, cbOutput);
free(certBytes);
cert->info.certificate = crypto_cert_read(certBytes, cbOutput);
if (!scCert->certificate)
if (!cert->info.certificate)
{
WLog_ERR(TAG, "unable to parse X509 certificate for key %s", scCert->containerName);
smartcardCert_Free(scCert);
WLog_ERR(TAG, "unable to parse X509 certificate for key %s", cert->info.containerName);
goto endofloop;
}
if (!treat_sc_cert(scCert))
{
smartcardCert_Free(scCert);
if (!treat_sc_cert(&cert->info))
goto endofloop;
}
if (userFilter && scCert->userHint && strcmp(scCert->userHint, userFilter) != 0)
if (userFilter && cert->info.userHint && strcmp(cert->info.userHint, userFilter) != 0)
{
smartcardCert_Free(scCert);
goto endofloop;
}
#ifndef _WIN32
if (!build_pkinit_args(settings, scCert))
if (!build_pkinit_args(settings, &cert->info))
{
WLog_ERR(TAG, "error build pkinit args");
smartcardCert_Free(scCert);
goto endofloop;
}
#endif
++*retCount;
scCert++;
endofloop:
free(certBytes);
if (phKey)
NCryptFreeObject((NCRYPT_HANDLE)phKey);
}
*scCerts = certs;
*retCount = (DWORD)certs->count;
ret = TRUE;
NCryptFreeObject((NCRYPT_HANDLE)provider);
@ -333,64 +419,113 @@ out:
return ret;
}
static BOOL smartcard_sw_enumerateCerts(const rdpSettings* settings, SmartcardCert* scCert,
DWORD count, DWORD* retCount)
static BOOL write_pem(const char* file, const char* pem)
{
size_t sz;
if (count < 1)
return FALSE;
if (!settings->SmartcardCertificateFile || !settings->SmartcardPrivateKeyFile)
{
WLog_ERR(TAG, "missing smartcard emulation cert or key");
size_t rc, size = strlen(pem) + 1;
FILE* fp = winpr_fopen(file, "w");
if (!fp)
return FALSE;
rc = fwrite(pem, 1, size, fp);
fclose(fp);
return rc == size;
}
/* 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);
static char* create_temporary_file(void)
{
BYTE buffer[32];
char* hex;
char* path;
scCert->certificate = crypto_cert_pem_read(settings->SmartcardCertificate);
if (!scCert->certificate)
winpr_RAND(buffer, sizeof(buffer));
hex = winpr_BinToHexString(buffer, sizeof(buffer), FALSE);
path = GetKnownSubPath(KNOWN_PATH_TEMP, hex);
free(hex);
return path;
}
static BOOL smartcard_sw_enumerateCerts(const rdpSettings* settings, SmartcardCerts** scCerts,
DWORD* retCount)
{
BOOL rc = FALSE;
int res;
SmartcardCerts* certs = NULL;
SmartcardCertInfoPrivate* cert;
const size_t count = 1;
char* keyPath = create_temporary_file();
char* certPath = create_temporary_file();
WINPR_ASSERT(settings);
WINPR_ASSERT(scCerts);
WINPR_ASSERT(retCount);
certs = calloc(count, sizeof(SmartcardCertInfoPrivate) + sizeof(SmartcardCerts));
if (!certs)
goto out_error;
certs->count = count;
cert = certs->certs = (SmartcardCertInfoPrivate*)(certs + 1);
cert->info.certificate = crypto_cert_pem_read(settings->SmartcardCertificate);
if (!cert->info.certificate)
{
WLog_ERR(TAG, "unable to read smartcard certificate");
goto out_error;
}
if (!treat_sc_cert(scCert))
if (!treat_sc_cert(&cert->info))
{
WLog_ERR(TAG, "unable to treat smartcard certificate");
goto out_error;
}
if (ConvertToUnicode(CP_UTF8, 0, "FreeRDP Emulator", -1, &scCert->reader, 0) < 0)
if (ConvertToUnicode(CP_UTF8, 0, "FreeRDP Emulator", -1, &cert->info.reader, 0) < 0)
goto out_error;
scCert->containerName = strdup("Private Key 00");
if (!scCert->containerName)
cert->info.containerName = strdup("Private Key 00");
if (!cert->info.containerName)
goto out_error;
*retCount = 1;
return TRUE;
/* compute PKINIT args FILE:<cert file>,<key file>
*
* We need files for PKINIT to read, so write the certificate to some
* temporary location and use that.
*/
if (!write_pem(keyPath, settings->SmartcardPrivateKey))
goto out_error;
if (!write_pem(certPath, settings->SmartcardCertificate))
goto out_error;
res = allocating_sprintf(&cert->info.pkinitArgs, "FILE:%s,%s", certPath, keyPath);
if (res <= 0)
goto out_error;
cert->certPath = certPath;
cert->keyPath = keyPath;
rc = TRUE;
*scCerts = certs;
*retCount = (DWORD)certs->count;
out_error:
smartcardCert_Free(scCert);
return FALSE;
if (!rc)
smartcardCerts_Free(certs);
return rc;
}
BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCert* scCert, DWORD count,
BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCerts** scCerts,
DWORD* retCount)
{
BOOL ret;
LPWSTR csp;
const char* asciiCsp = settings->CspName ? settings->CspName : MS_SCARD_PROV_A;
const char* asciiCsp;
WINPR_ASSERT(settings);
WINPR_ASSERT(scCerts);
WINPR_ASSERT(retCount);
asciiCsp = settings->CspName ? settings->CspName : MS_SCARD_PROV_A;
if (settings->SmartcardEmulation)
return smartcard_sw_enumerateCerts(settings, scCert, count, retCount);
return smartcard_sw_enumerateCerts(settings, scCerts, retCount);
if (ConvertToUnicode(CP_UTF8, 0, asciiCsp, -1, &csp, 0) <= 0)
{
@ -399,7 +534,16 @@ BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCert* scCert
}
ret = smartcard_hw_enumerateCerts(settings, csp, settings->ReaderName, settings->Username,
scCert, count, retCount);
scCerts, retCount);
free(csp);
return ret;
}
const SmartcardCertInfo* smartcard_getCertInfo(SmartcardCerts* scCerts, DWORD index)
{
WINPR_ASSERT(scCerts);
if (index >= scCerts->count)
return NULL;
return &scCerts->certs[index].info;
}

View File

@ -22,7 +22,9 @@
#include <freerdp/settings.h>
#include <freerdp/crypto/crypto.h>
struct _SmartcardCert
typedef struct sSmartCardCerts SmartcardCerts;
typedef struct
{
LPWSTR reader;
CryptoCert certificate;
@ -37,12 +39,12 @@ struct _SmartcardCert
BYTE atr[256];
DWORD atrLength;
BYTE sha1Hash[20];
};
typedef struct _SmartcardCert SmartcardCert;
} SmartcardCertInfo;
FREERDP_API void smartcardCert_Free(SmartcardCert* scCert);
FREERDP_API BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCert* scCert, DWORD count,
FREERDP_API BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCerts** scCert,
DWORD* retCount);
FREERDP_API const SmartcardCertInfo* smartcard_getCertInfo(SmartcardCerts* scCerts, DWORD index);
FREERDP_API void smartcardCerts_Free(SmartcardCerts* scCert);
#endif /* LIBFREERDP_CORE_SMARTCARDLOGON_H */

View File

@ -392,10 +392,8 @@ 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,