drdynvc: fix segfaults and a compiler warning

If we send a negative creation status while processing the DVC create
response pdu in drdynvc_process_create_request() we must also close
the created channel. Otherwise we will get duplicated channel IDs
in the channel manager's array list because the server will
eventually reuse the channel ids which we have reported as failed in
previous creation responses.
In order to protect the client from duplicated IDs sent by buggy or
malicious servers I've added an appropriate check in
dvcman_channel_new() which will now return NULL in this case.
Also added a missing NULL check for the result of dvcman_channel_new()
in dvcman_create_channel().
This commit is contained in:
Norbert Federa 2015-01-26 19:26:38 +01:00
parent b73e61de6b
commit 70c8acdd67
1 changed files with 14 additions and 2 deletions

View File

@ -28,7 +28,7 @@
#define TAG CHANNELS_TAG("drdynvc.client")
static void dvcman_channel_free(DVCMAN_CHANNEL* channel);
static void dvcman_channel_free(void* channel);
static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
{
@ -220,6 +220,12 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* pChannelMgr
{
DVCMAN_CHANNEL* channel;
if (dvcman_find_channel_by_id(pChannelMgr, ChannelId))
{
WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %d (%s)!", ChannelId, ChannelName);
return NULL;
}
channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
@ -234,8 +240,10 @@ static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* pChannelMgr
return channel;
}
void dvcman_channel_free(DVCMAN_CHANNEL* channel)
void dvcman_channel_free(void* arg)
{
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) arg;
if (channel->channel_callback)
{
channel->channel_callback->OnClose(channel->channel_callback);
@ -339,6 +347,9 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
channel = dvcman_channel_new(pChannelMgr, ChannelId, ChannelName);
if (!channel)
return 1;
channel->status = 1;
ArrayList_Add(dvcman->channels, channel);
@ -748,6 +759,7 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
{
WLog_DBG(TAG, "no listener");
Stream_Write_UINT32(data_out, (UINT32)(-1));
dvcman_close_channel(drdynvc->channel_mgr, ChannelId);
}
status = drdynvc_send(drdynvc, data_out);