Added new default certificate callbacks with extended information.
authorArmin Novak <armin.novak@thincast.com>
Fri, 30 Nov 2018 10:04:20 +0000 (11:04 +0100)
committerArmin Novak <armin.novak@thincast.com>
Tue, 4 Dec 2018 08:35:24 +0000 (09:35 +0100)
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.

client/Sample/tf_freerdp.c
client/Wayland/wlfreerdp.c
client/X11/xf_client.c
client/common/client.c
include/freerdp/client.h
libfreerdp/crypto/tls.c

index 05eb9ed..5549cb0 100644 (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;
index 00614cf..04a9c68 100644 (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);
 
index 8930cc9..8323c78 100644 (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);
index 7423811..7b2c54d 100644 (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);
@@ -529,9 +531,49 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
 }
 
 /** 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);
index 25049c0..8ade211 100644 (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));
index 632962b..31d5fda 100644 (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,