Remember accepted PEM cert to avoid unnecessary user input.
This commit is contained in:
parent
0d1895e4e7
commit
c9cebf6ed6
@ -85,24 +85,24 @@ struct rdp_tls
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int tls_connect(rdpTls* tls, BIO *underlying);
|
||||
FREERDP_API BOOL tls_accept(rdpTls* tls, BIO *underlying, rdpSettings *settings);
|
||||
FREERDP_API int tls_connect(rdpTls* tls, BIO* underlying);
|
||||
FREERDP_API BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings);
|
||||
FREERDP_API BOOL tls_send_alert(rdpTls* tls);
|
||||
|
||||
FREERDP_API int tls_write_all(rdpTls* tls, const BYTE* data, int length);
|
||||
|
||||
FREERDP_API int tls_set_alert_code(rdpTls* tls, int level, int description);
|
||||
|
||||
FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
|
||||
FREERDP_API BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname);
|
||||
FREERDP_API int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port);
|
||||
FREERDP_API void tls_print_certificate_error(char* hostname, UINT16 port,
|
||||
char* fingerprint, char* hosts_file);
|
||||
char* fingerprint, char* hosts_file);
|
||||
FREERDP_API void tls_print_certificate_name_mismatch_error(
|
||||
char* hostname, UINT16 port, char* common_name, char** alt_names,
|
||||
int alt_names_count);
|
||||
char* hostname, UINT16 port, char* common_name, char** alt_names,
|
||||
int alt_names_count);
|
||||
|
||||
FREERDP_API BOOL tls_print_error(char* func, SSL* connection, int value);
|
||||
|
||||
@ -110,7 +110,7 @@ FREERDP_API rdpTls* tls_new(rdpSettings* settings);
|
||||
FREERDP_API void tls_free(rdpTls* tls);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CRYPTO_TLS_H */
|
||||
|
@ -868,7 +868,9 @@ struct rdp_settings
|
||||
ALIGN64 char* PasswordHash; /* 24 */
|
||||
ALIGN64 BOOL WaitForOutputBufferFlush; /* 25 */
|
||||
ALIGN64 UINT32 MaxTimeInCheckLoop; /* 26 */
|
||||
UINT64 padding0064[64 - 27]; /* 27 */
|
||||
ALIGN64 char* AcceptedCert; /* 27 */
|
||||
ALIGN64 UINT32 AcceptedCertLength; /* 28 */
|
||||
UINT64 padding0064[64 - 29]; /* 29 */
|
||||
UINT64 padding0128[128 - 64]; /* 64 */
|
||||
|
||||
/**
|
||||
@ -1073,7 +1075,9 @@ struct rdp_settings
|
||||
ALIGN64 UINT32 TargetNetAddressCount; /* 1228 */
|
||||
ALIGN64 char** TargetNetAddresses; /* 1229 */
|
||||
ALIGN64 UINT32* TargetNetPorts; /* 1230 */
|
||||
UINT64 padding1280[1280 - 1231]; /* 1231 */
|
||||
ALIGN64 char* RedirectionAcceptedCert; /* 1231 */
|
||||
ALIGN64 UINT32 RedirectionAcceptedCertLength;/* 1232 */
|
||||
UINT64 padding1280[1280 - 1233]; /* 1233 */
|
||||
|
||||
/**
|
||||
* Security
|
||||
@ -1185,7 +1189,9 @@ struct rdp_settings
|
||||
ALIGN64 BOOL GatewayHttpTransport; /* 1995 */
|
||||
ALIGN64 BOOL GatewayUdpTransport; /* 1996 */
|
||||
ALIGN64 char* GatewayAccessToken; /* 1997 */
|
||||
UINT64 padding2015[2015 - 1998]; /* 1998 */
|
||||
ALIGN64 char* GatewayAcceptedCert; /* 1998 */
|
||||
ALIGN64 UINT32 GatewayAcceptedCertLength; /* 1999 */
|
||||
UINT64 padding2015[2015 - 2000]; /* 2000 */
|
||||
|
||||
/* Proxy */
|
||||
ALIGN64 UINT32 ProxyType; /* 2015 */
|
||||
@ -1501,7 +1507,7 @@ FREERDP_API int freerdp_addin_set_argument(ADDIN_ARGV* args, char* argument);
|
||||
FREERDP_API int freerdp_addin_replace_argument(ADDIN_ARGV* args, char* previous, char* argument);
|
||||
FREERDP_API int freerdp_addin_set_argument_value(ADDIN_ARGV* args, char* option, char* value);
|
||||
FREERDP_API int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, char* previous, char* option,
|
||||
char* value);
|
||||
char* value);
|
||||
|
||||
FREERDP_API BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device);
|
||||
FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name);
|
||||
@ -1511,13 +1517,13 @@ FREERDP_API void freerdp_device_collection_free(rdpSettings* settings);
|
||||
|
||||
FREERDP_API BOOL freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel);
|
||||
FREERDP_API ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings,
|
||||
const char* name);
|
||||
const char* name);
|
||||
FREERDP_API ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel);
|
||||
FREERDP_API void freerdp_static_channel_collection_free(rdpSettings* settings);
|
||||
|
||||
FREERDP_API BOOL freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel);
|
||||
FREERDP_API ADDIN_ARGV* freerdp_dynamic_channel_collection_find(rdpSettings* settings,
|
||||
const char* name);
|
||||
const char* name);
|
||||
FREERDP_API ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel);
|
||||
FREERDP_API void freerdp_dynamic_channel_collection_free(rdpSettings* settings);
|
||||
|
||||
@ -1528,7 +1534,7 @@ FREERDP_API void freerdp_performance_flags_split(rdpSettings* settings);
|
||||
|
||||
FREERDP_API void freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod);
|
||||
FREERDP_API void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled,
|
||||
UINT32 GatewayBypassLocal);
|
||||
UINT32 GatewayBypassLocal);
|
||||
|
||||
FREERDP_API BOOL freerdp_get_param_bool(rdpSettings* settings, int id);
|
||||
FREERDP_API int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param);
|
||||
|
@ -653,6 +653,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
CHECKED_STRDUP(Password); /* 22 */
|
||||
CHECKED_STRDUP(Domain); /* 23 */
|
||||
CHECKED_STRDUP(PasswordHash); /* 24 */
|
||||
CHECKED_STRDUP(AcceptedCert); /* 27 */
|
||||
_settings->ClientHostname = NULL; /* 134 */
|
||||
_settings->ClientProductId = NULL; /* 135 */
|
||||
CHECKED_STRDUP(AlternateShell); /* 640 */
|
||||
@ -668,6 +669,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
CHECKED_STRDUP(AllowedTlsCiphers); /* 1101 */
|
||||
CHECKED_STRDUP(NtlmSamFile); /* 1103 */
|
||||
CHECKED_STRDUP(PreconnectionBlob); /* 1155 */
|
||||
CHECKED_STRDUP(RedirectionAcceptedCert); /* 1231 */
|
||||
CHECKED_STRDUP(KerberosKdc); /* 1344 */
|
||||
CHECKED_STRDUP(KerberosRealm); /* 1345 */
|
||||
CHECKED_STRDUP(CertificateName); /* 1409 */
|
||||
@ -692,6 +694,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
CHECKED_STRDUP(GatewayPassword); /* 1988 */
|
||||
CHECKED_STRDUP(GatewayDomain); /* 1989 */
|
||||
CHECKED_STRDUP(GatewayAccessToken); /* 1997 */
|
||||
CHECKED_STRDUP(GatewayAcceptedCert); /* 1998 */
|
||||
CHECKED_STRDUP(ProxyHostname); /* 2016 */
|
||||
CHECKED_STRDUP(RemoteApplicationName); /* 2113 */
|
||||
CHECKED_STRDUP(RemoteApplicationIcon); /* 2114 */
|
||||
@ -772,7 +775,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
if (_settings->ChannelDefArraySize > 0)
|
||||
{
|
||||
_settings->ChannelDefArray = (CHANNEL_DEF*) calloc(settings->ChannelDefArraySize,
|
||||
sizeof(CHANNEL_DEF));
|
||||
sizeof(CHANNEL_DEF));
|
||||
|
||||
if (!_settings->ChannelDefArray)
|
||||
goto out_fail;
|
||||
@ -789,7 +792,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
|
||||
if (_settings->MonitorDefArraySize > 0)
|
||||
{
|
||||
_settings->MonitorDefArray = (rdpMonitor*) calloc(settings->MonitorDefArraySize,
|
||||
sizeof(rdpMonitor));
|
||||
sizeof(rdpMonitor));
|
||||
|
||||
if (!_settings->MonitorDefArray)
|
||||
goto out_fail;
|
||||
@ -1032,6 +1035,7 @@ void freerdp_settings_free(rdpSettings* settings)
|
||||
free(settings->Password);
|
||||
free(settings->Domain);
|
||||
free(settings->PasswordHash);
|
||||
free(settings->AcceptedCert);
|
||||
free(settings->AlternateShell);
|
||||
free(settings->ShellWorkingDirectory);
|
||||
free(settings->ComputerName);
|
||||
@ -1076,6 +1080,7 @@ void freerdp_settings_free(rdpSettings* settings)
|
||||
free(settings->RedirectionDomain);
|
||||
free(settings->RedirectionPassword);
|
||||
free(settings->RedirectionTsvUrl);
|
||||
free(settings->RedirectionAcceptedCert);
|
||||
free(settings->RemoteAssistanceSessionId);
|
||||
free(settings->RemoteAssistancePassword);
|
||||
free(settings->RemoteAssistancePassStub);
|
||||
@ -1086,6 +1091,7 @@ void freerdp_settings_free(rdpSettings* settings)
|
||||
free(settings->GatewayPassword);
|
||||
free(settings->GatewayDomain);
|
||||
free(settings->GatewayAccessToken);
|
||||
free(settings->GatewayAcceptedCert);
|
||||
free(settings->CertificateName);
|
||||
free(settings->DynamicDSTTimeZoneKeyName);
|
||||
free(settings->PreconnectionBlob);
|
||||
|
@ -1109,6 +1109,82 @@ BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length)
|
||||
{
|
||||
rdpSettings* settings = tls->settings;
|
||||
char* AccpetedKey;
|
||||
UINT32 AcceptedKeyLength;
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
AccpetedKey = settings->GatewayAcceptedCert;
|
||||
AcceptedKeyLength = settings->GatewayAcceptedCertLength;
|
||||
}
|
||||
else if (settings->RedirectionFlags != 0)
|
||||
{
|
||||
AccpetedKey = settings->RedirectionAcceptedCert;
|
||||
AcceptedKeyLength = settings->RedirectionAcceptedCertLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
AccpetedKey = settings->AcceptedCert;
|
||||
AcceptedKeyLength = settings->AcceptedCertLength;
|
||||
}
|
||||
|
||||
if (AcceptedKeyLength > 0)
|
||||
{
|
||||
if (AcceptedKeyLength == length)
|
||||
{
|
||||
if (memcmp(AccpetedKey, pem, AcceptedKeyLength) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
free(settings->GatewayAcceptedCert);
|
||||
settings->GatewayAcceptedCert = NULL;
|
||||
settings->GatewayAcceptedCertLength = 0;
|
||||
}
|
||||
else if (settings->RedirectionFlags != 0)
|
||||
{
|
||||
free(settings->RedirectionAcceptedCert);
|
||||
settings->RedirectionAcceptedCert = NULL;
|
||||
settings->RedirectionAcceptedCertLength = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(settings->AcceptedCert);
|
||||
settings->AcceptedCert = NULL;
|
||||
settings->AcceptedCertLength = 0;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL accept_cert(rdpTls* tls, const BYTE* pem, size_t length)
|
||||
{
|
||||
rdpSettings* settings = tls->settings;
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
settings->GatewayAcceptedCert = pem;
|
||||
settings->GatewayAcceptedCertLength = length;
|
||||
}
|
||||
else if (settings->RedirectionFlags != 0)
|
||||
{
|
||||
settings->RedirectionAcceptedCert = pem;
|
||||
settings->RedirectionAcceptedCertLength = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings->AcceptedCert = pem;
|
||||
settings->AcceptedCertLength = length;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
int port)
|
||||
{
|
||||
@ -1123,83 +1199,23 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
BOOL hostname_match = FALSE;
|
||||
BOOL verification_status = FALSE;
|
||||
rdpCertificateData* certificate_data;
|
||||
freerdp* instance = (freerdp*) tls->settings->instance;
|
||||
DWORD length;
|
||||
BYTE* pemCert;
|
||||
|
||||
if (!crypto_cert_get_public_key(cert, &pemCert, &length))
|
||||
return -1;
|
||||
|
||||
/* Check, if we already accepted this key. */
|
||||
if (is_accepted(tls, pemCert, length))
|
||||
{
|
||||
free(pemCert);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tls->settings->ExternalCertificateManagement)
|
||||
{
|
||||
BIO* bio;
|
||||
int status;
|
||||
int length;
|
||||
int offset;
|
||||
BYTE* pemCert;
|
||||
freerdp* instance = (freerdp*) tls->settings->instance;
|
||||
/**
|
||||
* Don't manage certificates internally, leave it up entirely to the external client implementation
|
||||
*/
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!bio)
|
||||
{
|
||||
WLog_ERR(TAG, "BIO_new() failure");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = PEM_write_bio_X509(bio, cert->px509);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
length = 2048;
|
||||
pemCert = (BYTE*) malloc(length + 1);
|
||||
|
||||
if (!pemCert)
|
||||
{
|
||||
WLog_ERR(TAG, "error allocating pemCert");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = BIO_read(bio, pemCert, length);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to read certificate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += status;
|
||||
|
||||
while (offset >= length)
|
||||
{
|
||||
int new_len;
|
||||
BYTE* new_cert;
|
||||
new_len = length * 2;
|
||||
new_cert = (BYTE*) realloc(pemCert, new_len + 1);
|
||||
|
||||
if (!new_cert)
|
||||
return -1;
|
||||
|
||||
length = new_len;
|
||||
pemCert = new_cert;
|
||||
status = BIO_read(bio, &pemCert[offset], length);
|
||||
|
||||
if (status < 0)
|
||||
break;
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to read certificate");
|
||||
return -1;
|
||||
}
|
||||
|
||||
length = offset;
|
||||
pemCert[length] = '\0';
|
||||
status = -1;
|
||||
int status = -1;
|
||||
|
||||
if (instance->VerifyX509Certificate)
|
||||
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname,
|
||||
@ -1207,8 +1223,12 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
else
|
||||
WLog_ERR(TAG, "No VerifyX509Certificate callback registered!");
|
||||
|
||||
free(pemCert);
|
||||
BIO_free(bio);
|
||||
if (status > 0)
|
||||
{
|
||||
accept_cert(tls, pemCert, length);
|
||||
}
|
||||
else
|
||||
free(pemCert);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
@ -1222,10 +1242,16 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
|
||||
/* ignore certificate verification if user explicitly required it (discouraged) */
|
||||
if (tls->settings->IgnoreCertificate)
|
||||
{
|
||||
free(pemCert);
|
||||
return 1; /* success! */
|
||||
}
|
||||
|
||||
if (!tls->isGatewayTransport && tls->settings->AuthenticationLevel == 0)
|
||||
{
|
||||
free(pemCert);
|
||||
return 1; /* success! */
|
||||
}
|
||||
|
||||
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
||||
if (!tls->isGatewayTransport && tls->settings->CertificateName)
|
||||
@ -1273,7 +1299,6 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
char* issuer;
|
||||
char* subject;
|
||||
char* fingerprint;
|
||||
freerdp* instance = (freerdp*) tls->settings->instance;
|
||||
DWORD accept_certificate = 0;
|
||||
issuer = crypto_cert_issuer(cert->px509);
|
||||
subject = crypto_cert_subject(cert->px509);
|
||||
@ -1384,6 +1409,15 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths,
|
||||
alt_names);
|
||||
|
||||
if (verification_status > 0)
|
||||
{
|
||||
accept_cert(tls, pemCert, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pemCert);
|
||||
}
|
||||
|
||||
return (verification_status == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user