Moved common code from cli clients to client lib.

This commit is contained in:
Armin Novak 2015-12-17 16:43:55 +01:00 committed by Armin Novak
parent 0e2208e942
commit b35f6658b9
4 changed files with 234 additions and 291 deletions

View File

@ -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;

View File

@ -102,8 +102,6 @@
#include <freerdp/log.h>
#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;

View File

@ -21,14 +21,21 @@
#include "config.h"
#endif
#include <string.h>
#include <errno.h>
#include <freerdp/client.h>
#include <freerdp/addin.h>
#include <freerdp/assistance.h>
#include <freerdp/client/file.h>
#include <freerdp/utils/passphrase.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
#include <freerdp/log.h>
#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);
}

View File

@ -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