Blame client/common/client.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * FreeRDP Client Common
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <string.h>
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/client.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/addin.h>
Packit 1fb8d4
#include <freerdp/assistance.h>
Packit 1fb8d4
#include <freerdp/client/file.h>
Packit 1fb8d4
#include <freerdp/utils/passphrase.h>
Packit 1fb8d4
#include <freerdp/client/cmdline.h>
Packit 1fb8d4
#include <freerdp/client/channels.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
#define TAG CLIENT_TAG("common")
Packit 1fb8d4
Packit 1fb8d4
static BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints;
Packit 1fb8d4
	return IFCALLRESULT(TRUE, pEntryPoints->ClientNew, instance, context);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void freerdp_client_common_free(freerdp* instance, rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints;
Packit 1fb8d4
	IFCALL(pEntryPoints->ClientFree, instance, context);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* Common API */
Packit 1fb8d4
Packit 1fb8d4
rdpContext* freerdp_client_context_new(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
Packit 1fb8d4
{
Packit 1fb8d4
	freerdp* instance;
Packit 1fb8d4
	rdpContext* context;
Packit 1fb8d4
Packit 1fb8d4
	if (!pEntryPoints)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	IFCALL(pEntryPoints->GlobalInit);
Packit 1fb8d4
	instance = freerdp_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!instance)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	instance->settings = pEntryPoints->settings;
Packit 1fb8d4
	instance->ContextSize = pEntryPoints->ContextSize;
Packit 1fb8d4
	instance->ContextNew = freerdp_client_common_new;
Packit 1fb8d4
	instance->ContextFree = freerdp_client_common_free;
Packit 1fb8d4
	instance->pClientEntryPoints = (RDP_CLIENT_ENTRY_POINTS*) malloc(
Packit 1fb8d4
	                                   pEntryPoints->Size);
Packit 1fb8d4
Packit 1fb8d4
	if (!instance->pClientEntryPoints)
Packit 1fb8d4
		goto out_fail;
Packit 1fb8d4
Packit 1fb8d4
	CopyMemory(instance->pClientEntryPoints, pEntryPoints, pEntryPoints->Size);
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_context_new(instance))
Packit 1fb8d4
		goto out_fail2;
Packit 1fb8d4
Packit 1fb8d4
	context = instance->context;
Packit 1fb8d4
	context->instance = instance;
Packit 1fb8d4
	context->settings = instance->settings;
Packit 1fb8d4
Packit 1fb8d4
	if (freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry,
Packit 1fb8d4
	                                    0) != CHANNEL_RC_OK)
Packit 1fb8d4
		goto out_fail2;
Packit 1fb8d4
Packit 1fb8d4
	return context;
Packit 1fb8d4
out_fail2:
Packit 1fb8d4
	free(instance->pClientEntryPoints);
Packit 1fb8d4
out_fail:
Packit 1fb8d4
	freerdp_free(instance);
Packit 1fb8d4
	return NULL;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void freerdp_client_context_free(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	freerdp* instance;
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	instance = context->instance;
Packit 1fb8d4
Packit 1fb8d4
	if (instance)
Packit 1fb8d4
	{
Packit 1fb8d4
		RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints;
Packit 1fb8d4
		freerdp_context_free(instance);
Packit 1fb8d4
Packit 1fb8d4
		if (pEntryPoints)
Packit 1fb8d4
			IFCALL(pEntryPoints->GlobalUninit);
Packit 1fb8d4
Packit 1fb8d4
		free(instance->pClientEntryPoints);
Packit 1fb8d4
		freerdp_free(instance);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_start(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	RDP_CLIENT_ENTRY_POINTS* pEntryPoints;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->instance || !context->instance->pClientEntryPoints)
Packit 1fb8d4
		return ERROR_BAD_ARGUMENTS;
Packit 1fb8d4
Packit 1fb8d4
	pEntryPoints = context->instance->pClientEntryPoints;
Packit 1fb8d4
	return IFCALLRESULT(CHANNEL_RC_OK, pEntryPoints->ClientStart, context);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_stop(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	RDP_CLIENT_ENTRY_POINTS* pEntryPoints;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !context->instance || !context->instance->pClientEntryPoints)
Packit 1fb8d4
		return ERROR_BAD_ARGUMENTS;
Packit 1fb8d4
Packit 1fb8d4
	pEntryPoints = context->instance->pClientEntryPoints;
Packit 1fb8d4
	return IFCALLRESULT(CHANNEL_RC_OK, pEntryPoints->ClientStop, context);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
freerdp* freerdp_client_get_instance(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context || !context->instance)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	return context->instance;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE freerdp_client_get_thread(rdpContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	return ((rdpClientContext*) context)->thread;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL freerdp_client_settings_post_process(rdpSettings* settings)
Packit 1fb8d4
{
Packit 1fb8d4
	/* Moved GatewayUseSameCredentials logic outside of cmdline.c, so
Packit 1fb8d4
	 * that the rdp file also triggers this functionality */
Packit 1fb8d4
	if (settings->GatewayEnabled)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (settings->GatewayUseSameCredentials)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (settings->Username)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(settings->GatewayUsername);
Packit 1fb8d4
				settings->GatewayUsername = _strdup(settings->Username);
Packit 1fb8d4
Packit 1fb8d4
				if (!settings->GatewayUsername)
Packit 1fb8d4
					goto out_error;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (settings->Domain)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(settings->GatewayDomain);
Packit 1fb8d4
				settings->GatewayDomain = _strdup(settings->Domain);
Packit 1fb8d4
Packit 1fb8d4
				if (!settings->GatewayDomain)
Packit 1fb8d4
					goto out_error;
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			if (settings->Password)
Packit 1fb8d4
			{
Packit 1fb8d4
				free(settings->GatewayPassword);
Packit 1fb8d4
				settings->GatewayPassword = _strdup(settings->Password);
Packit 1fb8d4
Packit 1fb8d4
				if (!settings->GatewayPassword)
Packit 1fb8d4
					goto out_error;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Moved logic for Multimon and Span monitors to force fullscreen, so
Packit 1fb8d4
	 * that the rdp file also triggers this functionality */
Packit 1fb8d4
	if (settings->SpanMonitors)
Packit 1fb8d4
	{
Packit 1fb8d4
		settings->UseMultimon = TRUE;
Packit 1fb8d4
		settings->Fullscreen = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (settings->UseMultimon)
Packit 1fb8d4
	{
Packit 1fb8d4
		settings->Fullscreen = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
out_error:
Packit 1fb8d4
	free(settings->GatewayUsername);
Packit 1fb8d4
	free(settings->GatewayDomain);
Packit 1fb8d4
	free(settings->GatewayPassword);
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc,
Packit 1fb8d4
        char** argv, BOOL allowUnknown)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
Packit 1fb8d4
	if (argc < 1)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	if (!argv)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	status = freerdp_client_settings_parse_command_line_arguments(settings, argc,
Packit 1fb8d4
	         argv, allowUnknown);
Packit 1fb8d4
Packit 1fb8d4
	if (status < 0)
Packit 1fb8d4
		return status;
Packit 1fb8d4
Packit 1fb8d4
	/* This function will call logic that is applicable to the settings
Packit 1fb8d4
	 * from command line parsing AND the rdp file parsing */
Packit 1fb8d4
	if (!freerdp_client_settings_post_process(settings))
Packit 1fb8d4
		status = -1;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_settings_parse_connection_file(rdpSettings* settings,
Packit 1fb8d4
        const char* filename)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpFile* file;
Packit 1fb8d4
	int ret = -1;
Packit 1fb8d4
	file = freerdp_client_rdp_file_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!file)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_client_parse_rdp_file(file, filename))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_client_populate_settings_from_rdp_file(file, settings))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	ret = 0;
Packit 1fb8d4
out:
Packit 1fb8d4
	freerdp_client_rdp_file_free(file);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_settings_parse_connection_file_buffer(rdpSettings* settings,
Packit 1fb8d4
        const BYTE* buffer, size_t size)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpFile* file;
Packit 1fb8d4
	int status = -1;
Packit 1fb8d4
	file = freerdp_client_rdp_file_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!file)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	if (freerdp_client_parse_rdp_file_buffer(file, buffer, size)
Packit 1fb8d4
	    && freerdp_client_populate_settings_from_rdp_file(file, settings))
Packit 1fb8d4
	{
Packit 1fb8d4
		status = 0;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	freerdp_client_rdp_file_free(file);
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_settings_write_connection_file(const rdpSettings* settings,
Packit 1fb8d4
        const char* filename, BOOL unicode)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpFile* file;
Packit 1fb8d4
	int ret = -1;
Packit 1fb8d4
	file = freerdp_client_rdp_file_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!file)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_client_populate_rdp_file_from_settings(file, settings))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_client_write_rdp_file(file, filename, unicode))
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	ret = 0;
Packit 1fb8d4
out:
Packit 1fb8d4
	freerdp_client_rdp_file_free(file);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int freerdp_client_settings_parse_assistance_file(rdpSettings* settings,
Packit 1fb8d4
        const char* filename)
Packit 1fb8d4
{
Packit 1fb8d4
	int status;
Packit 1fb8d4
	int ret = -1;
Packit 1fb8d4
	rdpAssistanceFile* file;
Packit 1fb8d4
	file = freerdp_assistance_file_new();
Packit 1fb8d4
Packit 1fb8d4
	if (!file)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	status = freerdp_assistance_parse_file(file, filename);
Packit 1fb8d4
Packit 1fb8d4
	if (status < 0)
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	status = freerdp_client_populate_settings_from_assistance_file(file, settings);
Packit 1fb8d4
Packit 1fb8d4
	if (status < 0)
Packit 1fb8d4
		goto out;
Packit 1fb8d4
Packit 1fb8d4
	ret = 0;
Packit 1fb8d4
out:
Packit 1fb8d4
	freerdp_assistance_file_free(file);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/** Callback set in the rdp_freerdp structure, and used to get the user's password,
Packit 1fb8d4
 *  if required to establish the connection.
Packit 1fb8d4
 *  This function is actually called in credssp_ntlmssp_client_init()
Packit 1fb8d4
 *  @see rdp_server_accept_nego() and rdp_check_fds()
Packit 1fb8d4
 *  @param instance - pointer to the rdp_freerdp structure that contains the connection settings
Packit 1fb8d4
 *  @param username - unused
Packit 1fb8d4
 *  @param password - on return: pointer to a character string that will be filled by the password entered by the user.
Packit 1fb8d4
 *  				  Note that this character string will be allocated inside the function, and needs to be deallocated by the caller
Packit 1fb8d4
 *  				  using free(), even in case this function fails.
Packit 1fb8d4
 *  @param domain - unused
Packit 1fb8d4
 *  @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details.
Packit 1fb8d4
 */
Packit 1fb8d4
static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway,
Packit 1fb8d4
                                        char** username,
Packit 1fb8d4
                                        char** password, char** domain)
Packit 1fb8d4
{
Packit 1fb8d4
	static const size_t password_size = 512;
Packit 1fb8d4
	const char* auth[] =
Packit 1fb8d4
	{
Packit 1fb8d4
		"Username: ",
Packit 1fb8d4
		"Domain:   ",
Packit 1fb8d4
		"Password: "
Packit 1fb8d4
	};
Packit 1fb8d4
	const char* gw[] =
Packit 1fb8d4
	{
Packit 1fb8d4
		"GatewayUsername: ",
Packit 1fb8d4
		"GatewayDomain:   ",
Packit 1fb8d4
		"GatewayPassword: "
Packit 1fb8d4
	};
Packit 1fb8d4
	const char** prompt = (gateway) ? gw : auth;
Packit 1fb8d4
Packit 1fb8d4
	if (!username || !password || !domain)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!*username)
Packit 1fb8d4
	{
Packit 1fb8d4
		size_t username_size = 0;
Packit 1fb8d4
		printf("%s", prompt[0]);
Packit 1fb8d4
Packit 1fb8d4
		if (GetLine(username, &username_size, stdin) < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno);
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (*username)
Packit 1fb8d4
		{
Packit 1fb8d4
			*username = StrSep(username, "\r");
Packit 1fb8d4
			*username = StrSep(username, "\n");
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!*domain)
Packit 1fb8d4
	{
Packit 1fb8d4
		size_t domain_size = 0;
Packit 1fb8d4
		printf("%s", prompt[1]);
Packit 1fb8d4
Packit 1fb8d4
		if (GetLine(domain, &domain_size, stdin) < 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno);
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (*domain)
Packit 1fb8d4
		{
Packit 1fb8d4
			*domain = StrSep(domain, "\r");
Packit 1fb8d4
			*domain = StrSep(domain, "\n");
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!*password)
Packit 1fb8d4
	{
Packit 1fb8d4
		*password = calloc(password_size, sizeof(char));
Packit 1fb8d4
Packit 1fb8d4
		if (!*password)
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
Packit 1fb8d4
		if (freerdp_passphrase_read(prompt[2], *password, password_size,
Packit 1fb8d4
		                            instance->settings->CredentialsFromStdin) == NULL)
Packit 1fb8d4
			goto fail;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
fail:
Packit 1fb8d4
	free(*username);
Packit 1fb8d4
	free(*domain);
Packit 1fb8d4
	free(*password);
Packit 1fb8d4
	*username = NULL;
Packit 1fb8d4
	*domain = NULL;
Packit 1fb8d4
	*password = NULL;
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL client_cli_authenticate(freerdp* instance, char** username,
Packit 1fb8d4
                             char** password, char** domain)
Packit 1fb8d4
{
Packit 1fb8d4
	if (instance->settings->SmartcardLogon)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_INFO(TAG, "Authentication via smartcard");
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return client_cli_authenticate_raw(instance, FALSE, username, password, domain);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL client_cli_gw_authenticate(freerdp* instance, char** username,
Packit 1fb8d4
                                char** password, char** domain)
Packit 1fb8d4
{
Packit 1fb8d4
	return client_cli_authenticate_raw(instance, TRUE, username, password, domain);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD client_cli_accept_certificate(rdpSettings* settings)
Packit 1fb8d4
{
Packit 1fb8d4
	char answer;
Packit 1fb8d4
Packit 1fb8d4
	if (settings->CredentialsFromStdin)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	while (1)
Packit 1fb8d4
	{
Packit 1fb8d4
		printf("Do you trust the above certificate? (Y/T/N) ");
Packit 1fb8d4
		fflush(stdout);
Packit 1fb8d4
		answer = fgetc(stdin);
Packit 1fb8d4
Packit 1fb8d4
		if (feof(stdin))
Packit 1fb8d4
		{
Packit 1fb8d4
			printf("\nError: Could not read answer from stdin.");
Packit 1fb8d4
Packit 1fb8d4
			if (settings->CredentialsFromStdin)
Packit 1fb8d4
				printf(" - Run without parameter \"--from-stdin\" to set trust.");
Packit 1fb8d4
Packit 1fb8d4
			printf("\n");
Packit 1fb8d4
			return 0;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		switch (answer)
Packit 1fb8d4
		{
Packit 1fb8d4
			case 'y':
Packit 1fb8d4
			case 'Y':
Packit 1fb8d4
				return 1;
Packit 1fb8d4
Packit 1fb8d4
			case 't':
Packit 1fb8d4
			case 'T':
Packit 1fb8d4
				return 2;
Packit 1fb8d4
Packit 1fb8d4
			case 'n':
Packit 1fb8d4
			case 'N':
Packit 1fb8d4
				return 0;
Packit 1fb8d4
Packit 1fb8d4
			default:
Packit 1fb8d4
				break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		printf("\n");
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
Packit 1fb8d4
 *  when the connection requires it.
Packit 1fb8d4
 *  This function will actually be called by tls_verify_certificate().
Packit 1fb8d4
 *  @see rdp_client_connect() and tls_connect()
Packit 1fb8d4
 *  @param instance - pointer to the rdp_freerdp structure that contains the connection settings
Packit 1fb8d4
 *  @param common_name
Packit 1fb8d4
 *  @param subject
Packit 1fb8d4
 *  @param issuer
Packit 1fb8d4
 *  @param fingerprint
Packit 1fb8d4
 *  @param host_mismatch Indicates the certificate host does not match.
Packit 1fb8d4
 *  @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
Packit 1fb8d4
 */
Packit 1fb8d4
DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
Packit 1fb8d4
                                    const char* subject, const char* issuer,
Packit 1fb8d4
                                    const char* fingerprint, BOOL host_mismatch)
Packit 1fb8d4
{
Packit 1fb8d4
	printf("Certificate details:\n");
Packit 1fb8d4
	printf("\tSubject: %s\n", subject);
Packit 1fb8d4
	printf("\tIssuer: %s\n", issuer);
Packit 1fb8d4
	printf("\tThumbprint: %s\n", fingerprint);
Packit 1fb8d4
	printf("The above X.509 certificate could not be verified, possibly because you do not have\n"
Packit 1fb8d4
	       "the CA certificate in your certificate store, or the certificate has expired.\n"
Packit 1fb8d4
	       "Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
Packit 1fb8d4
	return client_cli_accept_certificate(instance->settings);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
Packit 1fb8d4
 *  when a stored certificate does not match the remote counterpart.
Packit 1fb8d4
 *  This function will actually be called by tls_verify_certificate().
Packit 1fb8d4
 *  @see rdp_client_connect() and tls_connect()
Packit 1fb8d4
 *  @param instance - pointer to the rdp_freerdp structure that contains the connection settings
Packit 1fb8d4
 *  @param common_name
Packit 1fb8d4
 *  @param subject
Packit 1fb8d4
 *  @param issuer
Packit 1fb8d4
 *  @param fingerprint
Packit 1fb8d4
 *  @param old_subject
Packit 1fb8d4
 *  @param old_issuer
Packit 1fb8d4
 *  @param old_fingerprint
Packit 1fb8d4
 *  @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
Packit 1fb8d4
 */
Packit 1fb8d4
DWORD client_cli_verify_changed_certificate(freerdp* instance,
Packit 1fb8d4
        const char* common_name,
Packit 1fb8d4
        const char* subject, const char* issuer,
Packit 1fb8d4
        const char* fingerprint,
Packit 1fb8d4
        const char* old_subject, const char* old_issuer,
Packit 1fb8d4
        const char* old_fingerprint)
Packit 1fb8d4
{
Packit 1fb8d4
	printf("!!! Certificate has changed !!!\n");
Packit 1fb8d4
	printf("\n");
Packit 1fb8d4
	printf("New Certificate details:\n");
Packit 1fb8d4
	printf("\tSubject: %s\n", subject);
Packit 1fb8d4
	printf("\tIssuer: %s\n", issuer);
Packit 1fb8d4
	printf("\tThumbprint: %s\n", fingerprint);
Packit 1fb8d4
	printf("\n");
Packit 1fb8d4
	printf("Old Certificate details:\n");
Packit 1fb8d4
	printf("\tSubject: %s\n", old_subject);
Packit 1fb8d4
	printf("\tIssuer: %s\n", old_issuer);
Packit 1fb8d4
	printf("\tThumbprint: %s\n", old_fingerprint);
Packit 1fb8d4
	printf("\n");
Packit 1fb8d4
	printf("The above X.509 certificate does not match the certificate used for previous connections.\n"
Packit 1fb8d4
	       "This may indicate that the certificate has been tampered with.\n"
Packit 1fb8d4
	       "Please contact the administrator of the RDP server and clarify.\n");
Packit 1fb8d4
	return client_cli_accept_certificate(instance->settings);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL client_auto_reconnect(freerdp* instance)
Packit 1fb8d4
{
Packit 1fb8d4
	return client_auto_reconnect_ex(instance, NULL);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL client_auto_reconnect_ex(freerdp* instance, BOOL(*window_events)(freerdp* instance))
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 maxRetries;
Packit 1fb8d4
	UINT32 numRetries = 0;
Packit 1fb8d4
	rdpSettings* settings;
Packit 1fb8d4
Packit 1fb8d4
	if (!instance || !instance->settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	settings = instance->settings;
Packit 1fb8d4
	maxRetries = settings->AutoReconnectMaxRetries;
Packit 1fb8d4
Packit 1fb8d4
	/* Only auto reconnect on network disconnects. */
Packit 1fb8d4
	if (freerdp_error_info(instance) != 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	/* A network disconnect was detected */
Packit 1fb8d4
	WLog_INFO(TAG, "Network disconnect!");
Packit 1fb8d4
Packit 1fb8d4
	if (!settings->AutoReconnectionEnabled)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* No auto-reconnect - just quit */
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Perform an auto-reconnect. */
Packit 1fb8d4
	while (TRUE)
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT32 x;
Packit 1fb8d4
Packit 1fb8d4
		/* Quit retrying if max retries has been exceeded */
Packit 1fb8d4
		if ((maxRetries > 0) && (numRetries++ >= maxRetries))
Packit 1fb8d4
		{
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		/* Attempt the next reconnect */
Packit 1fb8d4
		WLog_INFO(TAG, "Attempting reconnect (%"PRIu32" of %"PRIu32")", numRetries, maxRetries);
Packit 1fb8d4
Packit 1fb8d4
		if (freerdp_reconnect(instance))
Packit 1fb8d4
			return TRUE;
Packit 1fb8d4
Packit 1fb8d4
		for (x = 0; x < 50; x++)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (!IFCALLRESULT(TRUE, window_events, instance))
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
Packit 1fb8d4
			Sleep(100);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	WLog_ERR(TAG, "Maximum reconnect retries exceeded");
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4