More abstracted proxy handling

This commit is contained in:
Christian Plattner 2016-12-10 23:13:35 +01:00
parent a72c184108
commit 58ef7cc42d
9 changed files with 152 additions and 79 deletions

View File

@ -23,6 +23,7 @@
#include "config.h"
#endif
#include <ctype.h>
#include <assert.h>
#include <winpr/crt.h>
@ -82,7 +83,7 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
{ "gt", COMMAND_LINE_VALUE_REQUIRED, "<rpc|http|auto>", NULL, NULL, -1, NULL, "Gateway transport type" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" },
{ "http-proxy", COMMAND_LINE_VALUE_REQUIRED, "<host>:<port>", NULL, NULL, -1, NULL, "HTTP Proxy" },
{ "proxy", COMMAND_LINE_VALUE_REQUIRED, "[<protocol>://]<host>:<port>", NULL, NULL, -1, NULL, "Proxy (see also environment variable below)" },
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" },
{ "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" },
{ "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" },
@ -1787,28 +1788,44 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->GatewayUseSameCredentials = TRUE;
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DIRECT);
}
CommandLineSwitchCase(arg, "http-proxy")
CommandLineSwitchCase(arg, "proxy")
{
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
p = strstr(arg->Value, "://");
if (p) {
*p = '\0';
if (!strcmp("http", arg->Value)) {
settings->ProxyType = PROXY_TYPE_HTTP;
} else {
WLog_ERR(TAG, "Only HTTP proxys supported by now");
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
}
arg->Value = p + 3;
}
p = strchr(arg->Value, ':');
if (p)
{
length = (int) (p - arg->Value);
settings->HTTPProxyPort = atoi(&p[1]);
settings->HTTPProxyHostname = (char*) malloc(length + 1);
strncpy(settings->HTTPProxyHostname, arg->Value, length);
settings->HTTPProxyHostname[length] = '\0';
if (!isdigit(p[1])) {
WLog_ERR(TAG, "Could not parse proxy port");
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
}
settings->ProxyPort = atoi(&p[1]);
settings->ProxyHostname = (char*) malloc(length + 1);
strncpy(settings->ProxyHostname, arg->Value, length);
settings->ProxyHostname[length] = '\0';
settings->HTTPProxyEnabled = TRUE;
}
else
{
/* TODO parse encironment variable here? */
fprintf(stderr, "Option http-proxy needs argument. Ignored.\n");
settings->ProxyType = PROXY_TYPE_HTTP;
}
}
else
{
WLog_ERR(TAG, "Option http-proxy needs argument.");
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
}
}
CommandLineSwitchCase(arg, "gu")
{

View File

@ -470,6 +470,9 @@ struct _RDPDR_PARALLEL
};
typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define PROXY_TYPE_NONE 0
#define PROXY_TYPE_HTTP 1
/* Settings */
#ifdef __GNUC__
@ -686,9 +689,9 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_GatewayRpcTransport 1994
#define FreeRDP_GatewayHttpTransport 1995
#define FreeRDP_GatewayUdpTransport 1996
#define FreeRDP_HTTPProxyEnabled 2015
#define FreeRDP_HTTPProxyHostname 2016
#define FreeRDP_HTTPProxyPort 2017
#define FreeRDP_ProxyType 2015
#define FreeRDP_ProxyHostname 2016
#define FreeRDP_ProxyPort 2017
#define FreeRDP_RemoteApplicationMode 2112
#define FreeRDP_RemoteApplicationName 2113
#define FreeRDP_RemoteApplicationIcon 2114
@ -1145,13 +1148,13 @@ struct rdp_settings
ALIGN64 BOOL GatewayRpcTransport; /* 1994 */
ALIGN64 BOOL GatewayHttpTransport; /* 1995 */
ALIGN64 BOOL GatewayUdpTransport; /* 1996 */
UINT64 padding2048[2048 - 1997]; /* 1997 */
UINT64 padding2112[2112 - 2048]; /* 2048 */
UINT64 padding2048[2015 - 1997]; /* 1997 */
/* HTTP Proxy */
ALIGN64 BOOL HTTPProxyEnabled; /* 1995 */
ALIGN64 char* HTTPProxyHostname; /* 1996 */
ALIGN64 UINT32 HTTPProxyPort; /* 1997 */
/* Proxy */
ALIGN64 UINT32 ProxyType; /* 2015 */
ALIGN64 char* ProxyHostname; /* 2016 */
ALIGN64 UINT16 ProxyPort; /* 2017 */
UINT64 padding2112[2112 - 2018]; /* 2018 */
/**
* RemoteApp

View File

@ -990,9 +990,6 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
case FreeRDP_GatewayUdpTransport:
return settings->GatewayUdpTransport;
case FreeRDP_HTTPProxyEnabled:
return settings->HTTPProxyEnabled;
case FreeRDP_RemoteApplicationMode:
return settings->RemoteApplicationMode;
@ -1476,10 +1473,6 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->GatewayUdpTransport = param;
break;
case FreeRDP_HTTPProxyEnabled:
settings->HTTPProxyEnabled = param;
break;
case FreeRDP_RemoteApplicationMode:
settings->RemoteApplicationMode = param;
break;
@ -1857,6 +1850,12 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id)
case FreeRDP_GatewayCredentialsSource:
return settings->GatewayCredentialsSource;
case FreeRDP_ProxyType:
return settings->ProxyType;
case FreeRDP_ProxyPort:
return settings->ProxyPort;
case FreeRDP_RemoteAppNumIconCaches:
return settings->RemoteAppNumIconCaches;
@ -2151,6 +2150,14 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
settings->GatewayCredentialsSource = param;
break;
case FreeRDP_ProxyType:
settings->ProxyType = param;
break;
case FreeRDP_ProxyPort:
settings->ProxyPort = param;
break;
case FreeRDP_RemoteAppNumIconCaches:
settings->RemoteAppNumIconCaches = param;
break;
@ -2480,6 +2487,9 @@ char* freerdp_get_param_string(rdpSettings* settings, int id)
case FreeRDP_GatewayDomain:
return settings->GatewayDomain;
case FreeRDP_ProxyHostname:
return settings->ProxyHostname;
case FreeRDP_RemoteApplicationName:
return settings->RemoteApplicationName;
@ -2687,8 +2697,8 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
tmp = &settings->GatewayDomain;
break;
case FreeRDP_HTTPProxyHostname:
tmp = &settings->HTTPProxyHostname;
case FreeRDP_ProxyHostname:
tmp = &settings->ProxyHostname;
break;
case FreeRDP_RemoteApplicationName:

View File

@ -902,17 +902,11 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim
BIO* bufferedBio = NULL;
rdpSettings* settings = rdg->settings;
const char *peerHostname = settings->GatewayHostname;
int peerPort = settings->GatewayPort;
BOOL isProxyConnection = FALSE;
UINT16 peerPort = settings->GatewayPort;
BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, TRUE);
assert(hostname != NULL);
if (settings->HTTPProxyEnabled) {
peerHostname = settings->HTTPProxyHostname;
peerPort = settings->HTTPProxyPort;
isProxyConnection = TRUE;
}
sockfd = freerdp_tcp_connect(rdg->context, settings, peerHostname,
peerPort, timeout);
@ -942,8 +936,8 @@ BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int tim
status = BIO_set_nonblock(bufferedBio, TRUE);
if (isProxyConnection) {
if (!http_proxy_connect(bufferedBio, settings->GatewayHostname, settings->GatewayPort))
return -1;
if (!proxy_connect(settings, bufferedBio, settings->GatewayHostname, settings->GatewayPort))
return FALSE;
}
if (!status)
@ -978,9 +972,9 @@ BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int time
assert(hostname != NULL);
if (settings->HTTPProxyEnabled) {
peerHostname = settings->HTTPProxyHostname;
peerPort = settings->HTTPProxyPort;
if (settings->ProxyType) {
peerHostname = settings->ProxyHostname;
peerPort = settings->ProxyPort;
isProxyConnection = TRUE;
}

View File

@ -760,14 +760,8 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
rdpContext* context = rpc->context;
rdpSettings* settings = context->settings;
const char *peerHostname = settings->GatewayHostname;
int peerPort = settings->GatewayPort;
BOOL isProxyConnection = FALSE;
if (settings->HTTPProxyEnabled) {
peerHostname = settings->HTTPProxyHostname;
peerPort = settings->HTTPProxyPort;
isProxyConnection = TRUE;
}
UINT16 peerPort = settings->GatewayPort;
BOOL isProxyConnection = proxy_prepare(settings, &peerHostname, &peerPort, TRUE);
sockfd = freerdp_tcp_connect(context, settings, peerHostname,
peerPort, timeout);
@ -793,7 +787,7 @@ int rpc_channel_tls_connect(RpcChannel* channel, int timeout)
return -1;
if (isProxyConnection) {
if (!http_proxy_connect(bufferedBio, settings->GatewayHostname, settings->GatewayPort))
if (!proxy_connect(settings, bufferedBio, settings->GatewayHostname, settings->GatewayPort))
return -1;
}

View File

@ -17,6 +17,7 @@
* limitations under the License.
*/
#include <ctype.h>
#include "proxy.h"
#include "freerdp/settings.h"
@ -27,40 +28,101 @@
#define CRLF "\r\n"
#define TAG FREERDP_TAG("core.proxy")
void http_proxy_read_environment(rdpSettings *settings, char *envname)
BOOL http_proxy_connect(BIO* bufferedBio, const char* hostname, UINT16 port);
void proxy_read_environment(rdpSettings *settings, char *envname);
BOOL proxy_prepare(rdpSettings *settings, const char **lpPeerHostname, UINT16 *lpPeerPort, BOOL isHTTPS)
{
/* For TSGateway, find the system HTTPS proxy automatically */
if (!settings->ProxyType)
proxy_read_environment(settings, "https_proxy");
if (!settings->ProxyType)
proxy_read_environment(settings, "HTTPS_PROXY");
if (settings->ProxyType) {
*lpPeerHostname = settings->ProxyHostname;
*lpPeerPort = settings->ProxyPort;
return TRUE;
}
return FALSE;
}
void proxy_read_environment(rdpSettings *settings, char *envname)
{
char env[256];
DWORD envlen;
char *hostname, *pport;
envlen = GetEnvironmentVariableA(envname, env, sizeof(env));
envlen = GetEnvironmentVariableA(envname, env, sizeof(env)-1);
if(!envlen)
return;
if (strncmp(env, "http://", 7)) {
WLog_ERR(TAG, "Proxy url must have scheme http. Ignoring.");
return;
env[envlen] = '\0';
proxy_parse_uri(settings, env);
}
BOOL proxy_parse_uri(rdpSettings *settings, const char *uri)
{
const char *hostname, *pport;
const char *protocol;
const char *p;
int hostnamelen;
p = strstr(uri, "://");
if (p) {
protocol = uri;
if (p == uri+4 && !strncmp("http", uri, 4)) {
settings->ProxyType = PROXY_TYPE_HTTP;
} else {
WLog_ERR(TAG, "Only HTTP proxys supported by now");
return FALSE;
}
uri = p + 3;
} else {
WLog_ERR(TAG, "No scheme in proxy URI");
return FALSE;
}
settings->HTTPProxyEnabled = TRUE;
hostname = env + 7;
hostname = uri;
pport = strchr(hostname, ':');
if (pport) {
*pport = '\0';
settings->HTTPProxyPort = atoi(pport+1);
if (!isdigit(*(pport+1))) {
WLog_ERR(TAG, "Could not parse proxy port");
return FALSE;
}
settings->ProxyPort = atoi(pport+1);
}
else {
/* The default is 80. Also for Proxys. */
settings->HTTPProxyPort = 80;
settings->ProxyPort = 80;
pport = strchr(hostname, '/');
if(pport)
*pport = '\0';
}
freerdp_set_param_string(settings, FreeRDP_HTTPProxyHostname, hostname);
WLog_INFO(TAG, "Parsed proxy configuration: %s:%d", settings->HTTPProxyHostname, settings->HTTPProxyPort);
if(pport) {
hostnamelen = pport - hostname;
} else {
hostnamelen = strlen(hostname);
}
settings->ProxyHostname = strndup(hostname, hostnamelen);
WLog_INFO(TAG, "Parsed proxy configuration: %s://%s:%d", protocol, settings->ProxyHostname, settings->ProxyPort);
return TRUE;
}
BOOL proxy_connect(rdpSettings *settings, BIO *bufferedBio, const char *hostname, UINT16 port)
{
switch (settings->ProxyType) {
case PROXY_TYPE_NONE:
return TRUE;
case PROXY_TYPE_HTTP:
return http_proxy_connect(bufferedBio, hostname, port);
default:
WLog_ERR(TAG, "Invalid internal proxy configuration");
return FALSE;
}
}
BOOL http_proxy_connect(BIO* bufferedBio, const char* hostname, UINT16 port)

View File

@ -23,7 +23,8 @@
#include "freerdp/settings.h"
#include <openssl/bio.h>
void http_proxy_read_environment(rdpSettings *settings, char *envname);
BOOL http_proxy_connect(BIO *bio, const char* hostname, UINT16 port);
BOOL proxy_prepare(rdpSettings *settings, const char **lpPeerHostname, UINT16 *lpPeerPort, BOOL isHTTPS);
BOOL proxy_parse_uri(rdpSettings *settings, const char *uri);
BOOL proxy_connect(rdpSettings *settings, BIO *bio, const char* hostname, UINT16 port);
#endif

View File

@ -670,7 +670,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
CHECKED_STRDUP(GatewayUsername); /* 1987 */
CHECKED_STRDUP(GatewayPassword); /* 1988 */
CHECKED_STRDUP(GatewayDomain); /* 1989 */
CHECKED_STRDUP(HTTPProxyHostname); /* 2016 */
CHECKED_STRDUP(ProxyHostname); /* 2016 */
CHECKED_STRDUP(RemoteApplicationName); /* 2113 */
CHECKED_STRDUP(RemoteApplicationIcon); /* 2114 */
CHECKED_STRDUP(RemoteApplicationProgram); /* 2115 */

View File

@ -51,7 +51,6 @@
#include "fastpath.h"
#include "transport.h"
#include "rdp.h"
#include "proxy.h"
#define TAG FREERDP_TAG("core.transport")
@ -225,13 +224,6 @@ BOOL transport_connect(rdpTransport* transport, const char* hostname,
if (transport->GatewayEnabled)
{
/* For TSGateway, find the system HTTPS proxy automatically */
if (!transport->settings->HTTPProxyEnabled)
http_proxy_read_environment(settings, "https_proxy");
if (!transport->settings->HTTPProxyEnabled)
http_proxy_read_environment(settings, "HTTPS_PROXY");
if (!status && settings->GatewayHttpTransport)
{
transport->rdg = rdg_new(transport);