Merge pull request #10474 from akallabeth/accepted-key-fix
[crypto,tls] fix AcceptedKey checks
This commit is contained in:
commit
92b547e91e
@ -65,6 +65,8 @@ extern "C"
|
||||
FREERDP_API char* freerdp_certificate_get_fingerprint(const rdpCertificate* certificate);
|
||||
FREERDP_API char* freerdp_certificate_get_pem(const rdpCertificate* certificate,
|
||||
size_t* pLength);
|
||||
FREERDP_API char* freerdp_certificate_get_pem_ex(const rdpCertificate* certificate,
|
||||
size_t* pLength, BOOL withCertChain);
|
||||
FREERDP_API BYTE* freerdp_certificate_get_der(const rdpCertificate* certificate,
|
||||
size_t* pLength);
|
||||
|
||||
|
@ -60,6 +60,8 @@ extern "C"
|
||||
FREERDP_API UINT16 freerdp_certificate_data_get_port(const rdpCertificateData* cert);
|
||||
|
||||
FREERDP_API const char* freerdp_certificate_data_get_pem(const rdpCertificateData* cert);
|
||||
FREERDP_API const char* freerdp_certificate_data_get_pem_ex(const rdpCertificateData* cert,
|
||||
BOOL withFullChain);
|
||||
FREERDP_API const char* freerdp_certificate_data_get_subject(const rdpCertificateData* cert);
|
||||
FREERDP_API const char* freerdp_certificate_data_get_issuer(const rdpCertificateData* cert);
|
||||
FREERDP_API const char*
|
||||
|
@ -1425,6 +1425,12 @@ fail:
|
||||
}
|
||||
|
||||
char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
|
||||
{
|
||||
return freerdp_certificate_get_pem_ex(cert, pLength, TRUE);
|
||||
}
|
||||
|
||||
char* freerdp_certificate_get_pem_ex(const rdpCertificate* cert, size_t* pLength,
|
||||
BOOL withCertChain)
|
||||
{
|
||||
char* pem = NULL;
|
||||
WINPR_ASSERT(cert);
|
||||
@ -1455,7 +1461,7 @@ char* freerdp_certificate_get_pem(const rdpCertificate* cert, size_t* pLength)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (cert->chain)
|
||||
if (cert->chain && withCertChain)
|
||||
{
|
||||
int count = sk_X509_num(cert->chain);
|
||||
for (int x = 0; x < count; x++)
|
||||
|
@ -48,6 +48,7 @@ struct rdp_certificate_data
|
||||
char* cached_issuer;
|
||||
char* cached_fingerprint;
|
||||
char* cached_pem;
|
||||
char* cached_pem_chain;
|
||||
};
|
||||
|
||||
/* ensure our hostnames (and therefore filenames) always use the same capitalization.
|
||||
@ -83,10 +84,15 @@ static BOOL freerdp_certificate_data_load_cache(rdpCertificateData* data)
|
||||
data->cached_subject = calloc(1, 1);
|
||||
|
||||
size_t pemlen = 0;
|
||||
data->cached_pem = freerdp_certificate_get_pem(data->cert, &pemlen);
|
||||
data->cached_pem = freerdp_certificate_get_pem_ex(data->cert, &pemlen, FALSE);
|
||||
if (!data->cached_pem)
|
||||
goto fail;
|
||||
|
||||
size_t pemchainlen = 0;
|
||||
data->cached_pem_chain = freerdp_certificate_get_pem_ex(data->cert, &pemchainlen, TRUE);
|
||||
if (!data->cached_pem_chain)
|
||||
goto fail;
|
||||
|
||||
data->cached_fingerprint = freerdp_certificate_get_fingerprint(data->cert);
|
||||
if (!data->cached_fingerprint)
|
||||
goto fail;
|
||||
@ -179,6 +185,7 @@ void freerdp_certificate_data_free(rdpCertificateData* data)
|
||||
free(data->cached_issuer);
|
||||
free(data->cached_fingerprint);
|
||||
free(data->cached_pem);
|
||||
free(data->cached_pem_chain);
|
||||
|
||||
free(data);
|
||||
}
|
||||
@ -198,9 +205,16 @@ UINT16 freerdp_certificate_data_get_port(const rdpCertificateData* cert)
|
||||
}
|
||||
|
||||
const char* freerdp_certificate_data_get_pem(const rdpCertificateData* cert)
|
||||
{
|
||||
return freerdp_certificate_data_get_pem_ex(cert, TRUE);
|
||||
}
|
||||
|
||||
const char* freerdp_certificate_data_get_pem_ex(const rdpCertificateData* cert, BOOL withFullChain)
|
||||
{
|
||||
if (!cert)
|
||||
return NULL;
|
||||
if (withFullChain)
|
||||
return cert->cached_pem_chain;
|
||||
return cert->cached_pem;
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ BOOL freerdp_certificate_store_save_data(rdpCertificateStore* store, const rdpCe
|
||||
if (!fp)
|
||||
goto fail;
|
||||
|
||||
fprintf(fp, "%s", freerdp_certificate_data_get_pem(data));
|
||||
fprintf(fp, "%s", freerdp_certificate_data_get_pem_ex(data, FALSE));
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
|
@ -1303,55 +1303,53 @@ static BOOL is_redirected(rdpTls* tls)
|
||||
return settings->RedirectionFlags != 0;
|
||||
}
|
||||
|
||||
static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length)
|
||||
static BOOL is_accepted(rdpTls* tls, const rdpCertificate* cert)
|
||||
{
|
||||
WINPR_ASSERT(tls);
|
||||
WINPR_ASSERT(tls->context);
|
||||
WINPR_ASSERT(cert);
|
||||
rdpSettings* settings = tls->context->settings;
|
||||
char* AccpetedKey = NULL;
|
||||
UINT32 AcceptedKeyLength = 0;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
FreeRDP_Settings_Keys_String keyAccepted;
|
||||
FreeRDP_Settings_Keys_UInt32 keyLength;
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
AccpetedKey = settings->GatewayAcceptedCert;
|
||||
AcceptedKeyLength = settings->GatewayAcceptedCertLength;
|
||||
keyAccepted = FreeRDP_GatewayAcceptedCert;
|
||||
keyLength = FreeRDP_GatewayAcceptedCertLength;
|
||||
}
|
||||
else if (is_redirected(tls))
|
||||
{
|
||||
AccpetedKey = settings->RedirectionAcceptedCert;
|
||||
AcceptedKeyLength = settings->RedirectionAcceptedCertLength;
|
||||
keyAccepted = FreeRDP_RedirectionAcceptedCert;
|
||||
keyLength = FreeRDP_RedirectionAcceptedCertLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
AccpetedKey = settings->AcceptedCert;
|
||||
AcceptedKeyLength = settings->AcceptedCertLength;
|
||||
keyAccepted = FreeRDP_AcceptedCert;
|
||||
keyLength = FreeRDP_AcceptedCertLength;
|
||||
}
|
||||
|
||||
if (AcceptedKeyLength > 0)
|
||||
const char* AcceptedKey = freerdp_settings_get_string(settings, keyAccepted);
|
||||
const UINT32 AcceptedKeyLength = freerdp_settings_get_uint32(settings, keyLength);
|
||||
|
||||
if ((AcceptedKeyLength > 0) && AcceptedKey)
|
||||
{
|
||||
if (AcceptedKeyLength == length)
|
||||
BOOL accepted = FALSE;
|
||||
size_t pemLength = 0;
|
||||
char* pem = freerdp_certificate_get_pem_ex(cert, &pemLength, FALSE);
|
||||
if (pem && (AcceptedKeyLength == pemLength))
|
||||
{
|
||||
if (memcmp(AccpetedKey, pem, AcceptedKeyLength) == 0)
|
||||
return TRUE;
|
||||
if (memcmp(AcceptedKey, pem, AcceptedKeyLength) == 0)
|
||||
accepted = TRUE;
|
||||
}
|
||||
free(pem);
|
||||
if (accepted)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
free(settings->GatewayAcceptedCert);
|
||||
settings->GatewayAcceptedCert = NULL;
|
||||
settings->GatewayAcceptedCertLength = 0;
|
||||
}
|
||||
else if (is_redirected(tls))
|
||||
{
|
||||
free(settings->RedirectionAcceptedCert);
|
||||
settings->RedirectionAcceptedCert = NULL;
|
||||
settings->RedirectionAcceptedCertLength = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(settings->AcceptedCert);
|
||||
settings->AcceptedCert = NULL;
|
||||
settings->AcceptedCertLength = 0;
|
||||
}
|
||||
freerdp_settings_set_string(settings, keyAccepted, NULL);
|
||||
freerdp_settings_set_uint32(settings, keyLength, 0);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -1425,13 +1423,17 @@ static BOOL is_accepted_fingerprint(const rdpCertificate* cert,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL accept_cert(rdpTls* tls, const BYTE* pem, UINT32 length)
|
||||
static BOOL accept_cert(rdpTls* tls, const rdpCertificate* cert)
|
||||
{
|
||||
WINPR_ASSERT(tls);
|
||||
WINPR_ASSERT(tls->context);
|
||||
WINPR_ASSERT(cert);
|
||||
|
||||
FreeRDP_Settings_Keys_String id = FreeRDP_AcceptedCert;
|
||||
FreeRDP_Settings_Keys_UInt32 lid = FreeRDP_AcceptedCertLength;
|
||||
|
||||
rdpSettings* settings = tls->context->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
@ -1444,13 +1446,18 @@ static BOOL accept_cert(rdpTls* tls, const BYTE* pem, UINT32 length)
|
||||
lid = FreeRDP_RedirectionAcceptedCertLength;
|
||||
}
|
||||
|
||||
if (!freerdp_settings_set_string_len(settings, id, (const char*)pem, length))
|
||||
return FALSE;
|
||||
size_t pemLength = 0;
|
||||
char* pem = freerdp_certificate_get_pem_ex(cert, &pemLength, FALSE);
|
||||
|
||||
return freerdp_settings_set_uint32(settings, lid, length);
|
||||
BOOL rc = FALSE;
|
||||
if (freerdp_settings_set_string_len(settings, id, pem, pemLength))
|
||||
rc = freerdp_settings_set_uint32(settings, lid, pemLength);
|
||||
free(pem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL tls_extract_pem(const rdpCertificate* cert, BYTE** PublicKey, size_t* PublicKeyLength)
|
||||
static BOOL tls_extract_full_pem(const rdpCertificate* cert, BYTE** PublicKey,
|
||||
size_t* PublicKeyLength)
|
||||
{
|
||||
if (!cert || !PublicKey)
|
||||
return FALSE;
|
||||
@ -1485,11 +1492,11 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
|
||||
if (freerdp_shall_disconnect_context(instance->context))
|
||||
return -1;
|
||||
|
||||
if (!tls_extract_pem(cert, &pemCert, &length))
|
||||
if (!tls_extract_full_pem(cert, &pemCert, &length))
|
||||
goto end;
|
||||
|
||||
/* Check, if we already accepted this key. */
|
||||
if (is_accepted(tls, pemCert, length))
|
||||
if (is_accepted(tls, cert))
|
||||
{
|
||||
verification_status = 1;
|
||||
goto end;
|
||||
@ -1520,7 +1527,7 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
|
||||
WLog_ERR(TAG, "No VerifyX509Certificate callback registered!");
|
||||
|
||||
if (verification_status > 0)
|
||||
accept_cert(tls, pemCert, length);
|
||||
accept_cert(tls, cert);
|
||||
else if (verification_status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %" PRIuz ") status: [%d] %s",
|
||||
@ -1780,7 +1787,7 @@ int tls_verify_certificate(rdpTls* tls, const rdpCertificate* cert, const char*
|
||||
}
|
||||
|
||||
if (verification_status > 0)
|
||||
accept_cert(tls, pemCert, length);
|
||||
accept_cert(tls, cert);
|
||||
}
|
||||
|
||||
end:
|
||||
|
Loading…
Reference in New Issue
Block a user