server: proxy: pf_context.c: Fix nla crash

Because the proxy uses freerdp_settings_copy to do re-negotiation after
first connection to remote server, all redirection information
(RedirectionPassword, RedirectionDomain, etc.) pointers were duplicated
(to both client and server settings structs). Then, at disconnection, a
double-free occured.
This commit is contained in:
kubistika 2019-08-13 15:06:45 +03:00 committed by akallabeth
parent 749c88ab0d
commit ef306fbff6
3 changed files with 18 additions and 11 deletions

View File

@ -100,8 +100,12 @@ static BOOL pf_client_pre_connect(freerdp* instance)
* GlyphCacheSupport must be explicitly set to GLYPH_SUPPORT_NONE. * GlyphCacheSupport must be explicitly set to GLYPH_SUPPORT_NONE.
*/ */
settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE; settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE;
/* proxy client should always try to connect with NLA */
settings->NlaSecurity = TRUE;
settings->OsMajorType = OSMAJORTYPE_UNIX; settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER; settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
/** /**
* settings->OrderSupport is initialized at this point. * settings->OrderSupport is initialized at this point.
* Only override it if you plan to implement custom order * Only override it if you plan to implement custom order
@ -336,14 +340,12 @@ static BOOL pf_client_global_init(void)
static int pf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) static int pf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
{ {
pClientContext* pc;
const char* str_data = freerdp_get_logon_error_info_data(data); const char* str_data = freerdp_get_logon_error_info_data(data);
const char* str_type = freerdp_get_logon_error_info_type(type); const char* str_type = freerdp_get_logon_error_info_type(type);
if (!instance || !instance->context) if (!instance || !instance->context)
return -1; return -1;
pc = (pClientContext*) instance->context;
WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type); WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type);
return 1; return 1;
} }

View File

@ -63,16 +63,21 @@ BOOL init_p_server_context(freerdp_peer* client)
return freerdp_peer_context_new(client); return freerdp_peer_context_new(client);
} }
void pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_server) /*
* pf_context_copy_settings copies settings from `src` to `dst`.
* when using this function, is_dst_server must be set to TRUE if the destination
* settings are server's settings. otherwise, they must be set to FALSE.
*/
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_dst_server)
{ {
rdpSettings* before_copy = freerdp_settings_clone(dst); rdpSettings* before_copy = freerdp_settings_clone(dst);
if (!before_copy) if (!before_copy)
return; return FALSE;
if (!freerdp_settings_copy(dst, src)) if (!freerdp_settings_copy(dst, src))
{ {
freerdp_settings_free(before_copy); freerdp_settings_free(before_copy);
return; return FALSE;
} }
free(dst->ConfigPath); free(dst->ConfigPath);
@ -83,10 +88,11 @@ void pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_
free(dst->CertificateFile); free(dst->CertificateFile);
free(dst->CertificateName); free(dst->CertificateName);
free(dst->CertificateContent); free(dst->CertificateContent);
free(dst->ClientRandom);
/* adjust pointer to instance pointer */ /* adjust pointer to instance pointer */
dst->ServerMode = is_server; dst->ServerMode = is_dst_server;
/* revert some values that must not be changed */
dst->ConfigPath = _strdup(before_copy->ConfigPath); dst->ConfigPath = _strdup(before_copy->ConfigPath);
dst->PrivateKeyContent = _strdup(before_copy->PrivateKeyContent); dst->PrivateKeyContent = _strdup(before_copy->PrivateKeyContent);
dst->RdpKeyContent = _strdup(before_copy->RdpKeyContent); dst->RdpKeyContent = _strdup(before_copy->RdpKeyContent);
@ -95,10 +101,8 @@ void pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_
dst->CertificateFile = _strdup(before_copy->CertificateFile); dst->CertificateFile = _strdup(before_copy->CertificateFile);
dst->CertificateName = _strdup(before_copy->CertificateName); dst->CertificateName = _strdup(before_copy->CertificateName);
dst->CertificateContent = _strdup(before_copy->CertificateContent); dst->CertificateContent = _strdup(before_copy->CertificateContent);
dst->ClientRandomLength = before_copy->ClientRandomLength;
CopyMemory(dst->ClientRandom, before_copy->ClientRandom, before_copy->ClientRandomLength);
if (is_server) if (is_dst_server)
{ {
free(dst->ServerCertificate); free(dst->ServerCertificate);
dst->ServerCertificateLength = before_copy->ServerCertificateLength; dst->ServerCertificateLength = before_copy->ServerCertificateLength;
@ -113,6 +117,7 @@ void pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_
} }
freerdp_settings_free(before_copy); freerdp_settings_free(before_copy);
return TRUE;
} }
rdpContext* p_client_context_create(rdpSettings* clientSettings) rdpContext* p_client_context_create(rdpSettings* clientSettings)

View File

@ -102,7 +102,7 @@ rdpContext* p_client_context_create(rdpSettings* clientSettings);
proxyData* proxy_data_new(); proxyData* proxy_data_new();
BOOL proxy_data_set_connection_info(proxyData* pdata, rdpSettings* ps, rdpSettings* pc); BOOL proxy_data_set_connection_info(proxyData* pdata, rdpSettings* ps, rdpSettings* pc);
void proxy_data_free(proxyData* pdata); void proxy_data_free(proxyData* pdata);
void pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_server); BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src, BOOL is_dst_server);
void proxy_data_abort_connect(proxyData* pdata); void proxy_data_abort_connect(proxyData* pdata);
BOOL proxy_data_shall_disconnect(proxyData* pdata); BOOL proxy_data_shall_disconnect(proxyData* pdata);