From b35f6658b9e1dd2fe6c5cffd2b7b6208cbe49d73 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 17 Dec 2015 16:43:55 +0100 Subject: [PATCH] Moved common code from cli clients to client lib. --- client/Wayland/wlfreerdp.c | 84 +-------------- client/X11/xf_client.c | 215 +------------------------------------ client/common/client.c | 214 ++++++++++++++++++++++++++++++++++++ include/freerdp/client.h | 12 +++ 4 files changed, 234 insertions(+), 291 deletions(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 2cc7597da..4aeda18cc 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -172,84 +172,6 @@ static void wl_post_disconnect(freerdp* instance) wlf_DestroyWindow(context, context->window); } -static DWORD wl_accept_certificate(rdpSettings* settings) -{ - char answer; - - while (1) - { - printf("Do you trust the above certificate? (Y/T/N) "); - answer = fgetc(stdin); - - if (feof(stdin)) - { - printf("\nError: Could not read answer from stdin."); - if (settings->CredentialsFromStdin) - printf(" - Run without parameter \"--from-stdin\" to set trust."); - printf("\n"); - return 0; - } - - switch(answer) - { - case 'y': - case 'Y': - return 1; - case 't': - case 'T': - return 2; - case 'n': - case 'N': - return 0; - default: - break; - } - printf("\n"); - } - - return 0; -} - -static DWORD wl_verify_certificate(freerdp* instance, const char* common_name, - const char* subject, const char* issuer, - const char* fingerprint, BOOL host_mismatch) -{ - printf("Certificate details:\n"); - 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 documentation on how to create local certificate store for a private CA.\n"); - - return wl_accept_certificate(instance->settings); -} - -static DWORD wl_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) -{ - printf("!!! Certificate has changed !!!\n"); - printf("\n"); - printf("New Certificate details:\n"); - 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 wl_accept_certificate(instance->settings); -} - static int wlfreerdp_run(freerdp* instance) { DWORD count; @@ -300,8 +222,10 @@ int main(int argc, char* argv[]) instance->PreConnect = wl_pre_connect; instance->PostConnect = wl_post_connect; instance->PostDisconnect = wl_post_disconnect; - instance->VerifyCertificate = wl_verify_certificate; - instance->VerifyChangedCertificate = wl_verify_changed_certificate; + 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->ContextSize = sizeof(wlfContext); instance->ContextNew = wl_context_new; diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index cfdd2f7d1..baaf7e75b 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -102,8 +102,6 @@ #include #define TAG CLIENT_TAG("x11") -static const size_t password_size = 512; - static int (*_def_error_handler)(Display*, XErrorEvent*); static int _xf_error_handler(Display* d, XErrorEvent* ev); static void xf_check_extensions(xfContext* context); @@ -1357,211 +1355,6 @@ static void xf_post_disconnect(freerdp* instance) xf_keyboard_free(xfc); } -/** Callback set in the rdp_freerdp structure, and used to get the user's password, - * if required to establish the connection. - * This function is actually called in credssp_ntlmssp_client_init() - * @see rdp_server_accept_nego() and rdp_check_fds() - * @param instance - pointer to the rdp_freerdp structure that contains the connection settings - * @param username - unused - * @param password - on return: pointer to a character string that will be filled by the password entered by the user. - * Note that this character string will be allocated inside the function, and needs to be deallocated by the caller - * using free(), even in case this function fails. - * @param domain - unused - * @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details. - */ -static BOOL xf_authenticate_raw(freerdp* instance, BOOL gateway, char** username, - char** password, char** domain) -{ - const char* auth[] = - { - "Username: ", - "Domain: ", - "Password: " - }; - const char* gw[] = - { - "GatewayUsername: ", - "GatewayDomain: ", - "GatewayPassword: " - }; - const char** prompt = (gateway) ? gw : auth; - - if (!username || !password || !domain) - return FALSE; - - if (!*username) - { - size_t username_size = 0; - printf("%s", prompt[0]); - if (getline(username, &username_size, stdin) < 0) - { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); - goto fail; - } - - if (*username) - { - *username = StrSep(username, "\r"); - *username = StrSep(username, "\n"); - } - } - - if (!*domain) - { - size_t domain_size = 0; - printf("%s", prompt[1]); - if (getline(domain, &domain_size, stdin) < 0) - { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); - goto fail; - } - - if (*domain) - { - *domain = StrSep(domain, "\r"); - *domain = StrSep(domain, "\n"); - } - } - - if (!*password) - { - *password = calloc(password_size, sizeof(char)); - if (!*password) - goto fail; - - if (freerdp_passphrase_read(prompt[2], *password, password_size, - instance->settings->CredentialsFromStdin) == NULL) - goto fail; - } - - return TRUE; - -fail: - free(*username); - free(*domain); - free(*password); - - *username = NULL; - *domain = NULL; - *password = NULL; - - return FALSE; -} - -static BOOL xf_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - return xf_authenticate_raw(instance, FALSE, username, password, domain); -} - -static BOOL xf_gw_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - return xf_authenticate_raw(instance, TRUE, username, password, domain); -} - -static DWORD xf_accept_certificate(rdpSettings* settings) -{ - char answer; - - while (1) - { - printf("Do you trust the above certificate? (Y/T/N) "); - answer = fgetc(stdin); - - if (feof(stdin)) - { - printf("\nError: Could not read answer from stdin."); - if (settings->CredentialsFromStdin) - printf(" - Run without parameter \"--from-stdin\" to set trust."); - printf("\n"); - return 0; - } - - switch(answer) - { - case 'y': - case 'Y': - return 1; - case 't': - case 'T': - return 2; - case 'n': - case 'N': - return 0; - default: - break; - } - printf("\n"); - } - - return 0; -} - -/** 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 common_name - * @param subject - * @param issuer - * @param fingerprint - * @param host_mismatch Indicates the certificate host does not match. - * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. - */ -static DWORD xf_verify_certificate(freerdp* instance, const char* common_name, - const char* subject, const char* issuer, - const char* fingerprint, BOOL host_mismatch) -{ - printf("Certificate details:\n"); - 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 documentation on how to create local certificate store for a private CA.\n"); - - return xf_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 common_name - * @param subject - * @param issuer - * @param fingerprint - * @param old_subject - * @param old_issuer - * @param old_fingerprint - * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. - */ -static DWORD xf_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) -{ - printf("!!! Certificate has changed !!!\n"); - printf("\n"); - printf("New Certificate details:\n"); - 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 xf_accept_certificate(instance->settings); -} - int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) { xfContext* xfc = (xfContext*) instance->context; @@ -2009,10 +1802,10 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; instance->PostDisconnect = xf_post_disconnect; - instance->Authenticate = xf_authenticate; - instance->GatewayAuthenticate = xf_gw_authenticate; - instance->VerifyCertificate = xf_verify_certificate; - instance->VerifyChangedCertificate = xf_verify_changed_certificate; + 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->LogonErrorInfo = xf_logon_error_info; settings = instance->settings; diff --git a/client/common/client.c b/client/common/client.c index 4da191912..3a59d5ab6 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -21,14 +21,21 @@ #include "config.h" #endif +#include +#include + #include #include #include #include +#include #include #include +#include +#define TAG CLIENT_TAG("common") + static BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context) { RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; @@ -296,3 +303,210 @@ int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const c return 0; } +/** Callback set in the rdp_freerdp structure, and used to get the user's password, + * if required to establish the connection. + * This function is actually called in credssp_ntlmssp_client_init() + * @see rdp_server_accept_nego() and rdp_check_fds() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param username - unused + * @param password - on return: pointer to a character string that will be filled by the password entered by the user. + * Note that this character string will be allocated inside the function, and needs to be deallocated by the caller + * using free(), even in case this function fails. + * @param domain - unused + * @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details. + */ +static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway, char** username, + char** password, char** domain) +{ + static const size_t password_size = 512; + const char* auth[] = + { + "Username: ", + "Domain: ", + "Password: " + }; + const char* gw[] = + { + "GatewayUsername: ", + "GatewayDomain: ", + "GatewayPassword: " + }; + const char** prompt = (gateway) ? gw : auth; + + if (!username || !password || !domain) + return FALSE; + + if (!*username) + { + size_t username_size = 0; + printf("%s", prompt[0]); + if (getline(username, &username_size, stdin) < 0) + { + WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); + goto fail; + } + + if (*username) + { + *username = StrSep(username, "\r"); + *username = StrSep(username, "\n"); + } + } + + if (!*domain) + { + size_t domain_size = 0; + printf("%s", prompt[1]); + if (getline(domain, &domain_size, stdin) < 0) + { + WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); + goto fail; + } + + if (*domain) + { + *domain = StrSep(domain, "\r"); + *domain = StrSep(domain, "\n"); + } + } + + if (!*password) + { + *password = calloc(password_size, sizeof(char)); + if (!*password) + goto fail; + + if (freerdp_passphrase_read(prompt[2], *password, password_size, + instance->settings->CredentialsFromStdin) == NULL) + goto fail; + } + + return TRUE; + +fail: + free(*username); + free(*domain); + free(*password); + + *username = NULL; + *domain = NULL; + *password = NULL; + + return FALSE; +} + +BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + return client_cli_authenticate_raw(instance, FALSE, username, password, domain); +} + +BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + return client_cli_authenticate_raw(instance, TRUE, username, password, domain); +} + +static DWORD client_cli_accept_certificate(rdpSettings* settings) +{ + char answer; + + while (1) + { + printf("Do you trust the above certificate? (Y/T/N) "); + answer = fgetc(stdin); + + if (feof(stdin)) + { + printf("\nError: Could not read answer from stdin."); + if (settings->CredentialsFromStdin) + printf(" - Run without parameter \"--from-stdin\" to set trust."); + printf("\n"); + return 0; + } + + switch(answer) + { + case 'y': + case 'Y': + return 1; + case 't': + case 'T': + return 2; + case 'n': + case 'N': + return 0; + default: + break; + } + printf("\n"); + } + + return 0; +} + +/** 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 common_name + * @param subject + * @param issuer + * @param fingerprint + * @param host_mismatch Indicates the certificate host does not match. + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) +{ + printf("Certificate details:\n"); + 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 documentation on how to create local certificate store for a private CA.\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() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name + * @param subject + * @param issuer + * @param fingerprint + * @param old_subject + * @param old_issuer + * @param old_fingerprint + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +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) +{ + printf("!!! Certificate has changed !!!\n"); + printf("\n"); + printf("New Certificate details:\n"); + 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); +} + + diff --git a/include/freerdp/client.h b/include/freerdp/client.h index 39708c77e..f807b2fc2 100644 --- a/include/freerdp/client.h +++ b/include/freerdp/client.h @@ -94,6 +94,18 @@ FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings* FREERDP_API int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const char* filename); +FREERDP_API BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain); +FREERDP_API BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain); + +FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch); + +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); #ifdef __cplusplus } #endif