Removed Smartcard files from settings
* Removed file names from settings * Added temporary file creation for pkinit
This commit is contained in:
parent
649527ef8d
commit
b3790d7454
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
@ -1159,21 +1157,19 @@ struct rdp_settings
|
||||
UINT64 padding1284[1285 - 1284]; /* 1284 */
|
||||
|
||||
/* Settings used for smartcard emulation */
|
||||
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 */
|
||||
UINT64 padding1344[1344 - 1299]; /* 1299 */
|
||||
ALIGN64 char* SmartcardCertificate; /* 1285 */
|
||||
ALIGN64 char* SmartcardPrivateKey; /* 1286 */
|
||||
ALIGN64 char* SmartcardPin; /* 1287 */
|
||||
ALIGN64 BOOL SmartcardEmulation; /* 1288 */
|
||||
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 */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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" },
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
NCryptFreeObject((NCRYPT_HANDLE)phKey);
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
if (!settings->SmartcardCertificateFile || !settings->SmartcardPrivateKeyFile)
|
||||
{
|
||||
WLog_ERR(TAG, "missing smartcard emulation cert or key");
|
||||
return FALSE;
|
||||
}
|
||||
static char* create_temporary_file(void)
|
||||
{
|
||||
BYTE buffer[32];
|
||||
char* hex;
|
||||
char* path;
|
||||
|
||||
/* 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);
|
||||
winpr_RAND(buffer, sizeof(buffer));
|
||||
hex = winpr_BinToHexString(buffer, sizeof(buffer), FALSE);
|
||||
path = GetKnownSubPath(KNOWN_PATH_TEMP, hex);
|
||||
free(hex);
|
||||
return path;
|
||||
}
|
||||
|
||||
scCert->certificate = crypto_cert_pem_read(settings->SmartcardCertificate);
|
||||
if (!scCert->certificate)
|
||||
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;
|
||||
}
|
||||
|
@ -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, SmartcardCerts** scCert,
|
||||
DWORD* retCount);
|
||||
FREERDP_API const SmartcardCertInfo* smartcard_getCertInfo(SmartcardCerts* scCerts, DWORD index);
|
||||
FREERDP_API void smartcardCerts_Free(SmartcardCerts* scCert);
|
||||
|
||||
FREERDP_API BOOL smartcard_enumerateCerts(const rdpSettings* settings, SmartcardCert* scCert, DWORD count,
|
||||
DWORD* retCount);
|
||||
|
||||
#endif /* LIBFREERDP_CORE_SMARTCARDLOGON_H */
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user