Added new default certificate callbacks with extended information.

The extended information provided by VerifyCertificateEx and
VerifyChangedCertificateEx is now exploited by the new functions
client_cli_verify_certificate_ex and client_cli_verify_changed_certificate_ex.

The old callbacks now print out deprecation warnings to inform the
user and developer about this deprecation.
This commit is contained in:
Armin Novak 2018-11-30 11:04:20 +01:00
parent a8823fdf95
commit e04c319d21
6 changed files with 120 additions and 8 deletions

View File

@ -107,11 +107,9 @@ static BOOL tf_pre_connect(freerdp* instance)
/* Optional OS identifier sent to server */
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
/* settings->OrderSupport is initialized at this point.
* Only override it if you plan to implement custom order
* callbacks or deactiveate certain features. */
/* Register the channel listeners.
* They are required to set up / tear down channels if they are loaded. */
PubSub_SubscribeChannelConnected(instance->context->pubSub,
@ -262,8 +260,8 @@ static BOOL tf_client_new(freerdp* instance, rdpContext* context)
instance->PostDisconnect = tf_post_disconnect;
instance->Authenticate = client_cli_authenticate;
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificate = client_cli_verify_certificate;
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->LogonErrorInfo = tf_logon_error_info;
/* TODO: Client display set up */
return TRUE;

View File

@ -386,8 +386,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
instance->PostDisconnect = wl_post_disconnect;
instance->Authenticate = client_cli_authenticate;
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificate = client_cli_verify_certificate;
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->LogonErrorInfo = wlf_logon_error_info;
wfl->display = UwacOpenDisplay(NULL, &status);

View File

@ -1763,8 +1763,8 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->PostDisconnect = xf_post_disconnect;
instance->Authenticate = client_cli_authenticate;
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificate = client_cli_verify_certificate;
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->LogonErrorInfo = xf_logon_error_info;
PubSub_SubscribeTerminate(context->pubSub,
xf_TerminateEventHandler);

View File

@ -506,6 +506,7 @@ static DWORD client_cli_accept_certificate(rdpSettings* settings)
* when the connection requires it.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @deprecated Use client_cli_verify_certificate_ex
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param common_name
* @param subject
@ -518,6 +519,7 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch)
{
printf("WARNING: This callback is deprecated, migrate to client_cli_verify_certificate_ex\n");
printf("Certificate details:\n");
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
@ -528,10 +530,50 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
return client_cli_accept_certificate(instance->settings);
}
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
* when the connection requires it.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
* @param host The host currently connecting to
* @param port The port currently connecting to
* @param common_name The common name of the certificate, should match host or an alias of it
* @param subject The subject of the certificate
* @param issuer The certificate issuer name
* @param fingerprint The fingerprint of the certificate
* @param flags See VERIFY_CERT_FLAG_* for possible values.
*
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
*/
DWORD client_cli_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, DWORD flags)
{
const char* type = "RDP-Server";
if (flags & VERIFY_CERT_FLAG_GATEWAY)
type = "RDP-Gateway";
if (flags & VERIFY_CERT_FLAG_REDIRECT)
type = "RDP-Redirect";
printf("Certificate details for %s:%"PRIu16" (%s):\n", host, port, type);
printf("\tCommon Name: %s\n", common_name);
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
printf("The above X.509 certificate could not be verified, possibly because you do not have\n"
"the CA certificate in your certificate store, or the certificate has expired.\n"
"Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
return client_cli_accept_certificate(instance->settings);
}
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
* when a stored certificate does not match the remote counterpart.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @deprecated Use client_cli_verify_changed_certificate_ex
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param common_name
* @param subject
@ -549,6 +591,7 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint)
{
printf("WARNING: This callback is deprecated, migrate to client_cli_verify_changed_certificate_ex\n");
printf("!!! Certificate has changed !!!\n");
printf("\n");
printf("New Certificate details:\n");
@ -567,6 +610,59 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
return client_cli_accept_certificate(instance->settings);
}
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
* when a stored certificate does not match the remote counterpart.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
* @param host The host currently connecting to
* @param port The port currently connecting to
* @param common_name The common name of the certificate, should match host or an alias of it
* @param subject The subject of the certificate
* @param issuer The certificate issuer name
* @param fingerprint The fingerprint of the certificate
* @param old_subject The subject of the previous certificate
* @param old_issuer The previous certificate issuer name
* @param old_fingerprint The fingerprint of the previous certificate
* @param flags See VERIFY_CERT_FLAG_* for possible values.
*
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
*/
DWORD client_cli_verify_changed_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint, DWORD flags)
{
const char* type = "RDP-Server";
if (flags & VERIFY_CERT_FLAG_GATEWAY)
type = "RDP-Gateway";
if (flags & VERIFY_CERT_FLAG_REDIRECT)
type = "RDP-Redirect";
printf("!!!Certificate for %s:%"PRIu16" (%s) has changed!!!\n", host, port, type);
printf("\n");
printf("New Certificate details:\n");
printf("\tCommon Name: %s\n", common_name);
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
printf("\n");
printf("Old Certificate details:\n");
printf("\tSubject: %s\n", old_subject);
printf("\tIssuer: %s\n", old_issuer);
printf("\tThumbprint: %s\n", old_fingerprint);
printf("\n");
printf("The above X.509 certificate does not match the certificate used for previous connections.\n"
"This may indicate that the certificate has been tampered with.\n"
"Please contact the administrator of the RDP server and clarify.\n");
return client_cli_accept_certificate(instance->settings);
}
BOOL client_auto_reconnect(freerdp* instance)
{
return client_auto_reconnect_ex(instance, NULL);

View File

@ -107,11 +107,25 @@ FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* c
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch);
FREERDP_API DWORD client_cli_verify_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, DWORD flags);
FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint);
FREERDP_API DWORD client_cli_verify_changed_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint, DWORD flags);
FREERDP_API BOOL client_auto_reconnect(freerdp* instance);
FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
BOOL(*window_events)(freerdp* instance));

View File

@ -1461,6 +1461,8 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, const char* hostname,
}
else if (instance->VerifyCertificate)
{
WLog_WARN(TAG,
"The VerifyCertificate callback is deprecated, migrate your application to VerifyCertificateEx");
accept_certificate = instance->VerifyCertificate(
instance, common_name,
subject, issuer,
@ -1503,6 +1505,8 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, const char* hostname,
}
else if (instance->VerifyChangedCertificate)
{
WLog_WARN(TAG,
"The VerifyChangedCertificate callback is deprecated, migrate your application to VerifyChangedCertificateEx");
accept_certificate = instance->VerifyChangedCertificate(
instance, common_name, subject, issuer,
fingerprint, old_subject, old_issuer,