Use proper user-initiated disconnect sequence

A correct user initated disconnect sequence should send
a MCS Disconnect Provider Ultimatum PDU defined in T.128
upon a disconnect. This commit adds the implementation
the mentioned PDU and the actual write of the packet.

Signed-off-by: Henrik Andersson <hean01@cendio.com>
This commit is contained in:
Cendio 2018-01-22 13:04:41 +01:00
parent 293680c034
commit e112b69c61
5 changed files with 61 additions and 3 deletions

View File

@ -126,6 +126,17 @@ enum MCS_PDU_TYPE
#define MCS_GLOBAL_CHANNEL 1003
#define MCS_USERCHANNEL_BASE 1001
/* ITU-T Rec. T.125, Reason enumeration used with Disconnect Provider
Ultimatum, see mcs_send_dpu(reason) */
enum MCS_DPU_REASON
{
RN_DOMAIN_DISCONNECTED = 0,
RN_PROVIDER_INITIATED,
RN_TOKEN_PURGED,
RN_USER_REQUESTED,
RN_CHANNEL_PURGED,
};
/* RDP secure transport constants */
#define SEC_RANDOM_SIZE 32
#define SEC_MODULUS_SIZE 64

29
mcs.c
View File

@ -237,6 +237,32 @@ mcs_recv_cjcf(void)
return s_check_end(s);
}
/* Send MCS Disconnect provider ultimatum PDU */
void
mcs_send_dpu(unsigned short reason)
{
STREAM s, contents;
logger(Protocol, Debug, "mcs_send_dpu(), reason=%d", reason);
contents = malloc(sizeof(struct stream));
memset(contents, 0, sizeof(struct stream));
s_realloc(contents, 6);
s_reset(contents);
ber_out_integer(contents, reason); /* Reason */
ber_out_sequence(contents, NULL); /* SEQUENCE OF NonStandradParameters OPTIONAL */
s_mark_end(contents);
s = iso_init(8);
ber_out_sequence(s, contents);
s_free(contents);
s_mark_end(s);
iso_send(s);
}
/* Initialise an MCS transport data packet */
STREAM
mcs_init(int length)
@ -353,8 +379,9 @@ mcs_connect_finalize(STREAM mcs_data)
/* Disconnect from the MCS layer */
void
mcs_disconnect(void)
mcs_disconnect(int reason)
{
mcs_send_dpu(reason);
iso_disconnect();
}

View File

@ -99,7 +99,7 @@ STREAM mcs_recv(uint16 * channel, uint8 * rdpver);
RD_BOOL mcs_connect_start(char *server, char *username, char *domain, char *password,
RD_BOOL reconnect, uint32 * selected_protocol);
RD_BOOL mcs_connect_finalize(STREAM s);
void mcs_disconnect(void);
void mcs_disconnect(int reason);
void mcs_reset_state(void);
/* orders.c */
void process_orders(STREAM s, uint16 num_orders);

View File

@ -958,7 +958,9 @@ sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL
void
sec_disconnect(void)
{
mcs_disconnect();
/* Perform a User-initiated disconnect sequence, see
[MS-RDPBCGR] 1.3.1.4 Disconnect Sequences */
mcs_disconnect(RN_USER_REQUESTED);
}
/* reset the state of the sec layer */

View File

@ -81,3 +81,21 @@ Ensure(MCS, should_produce_valid_packet_for_McsSendCJrq)
mcs_send_cjrq(chan_id);
s_free(s);
}
/* Test function */
Ensure(MCS, should_produce_valid_packet_for_McsSendDPU)
{
int reason = 1;
struct stream *s;
uint8_t content[] = {0x30, 0x06, 0x02, 0x02, 0x00, reason, 0x30, 0x00};
s = stream_new(8);
expect(logger);
expect(iso_init, will_return(s));
expect(iso_send, when(stream->data, is_equal_to_contents_of(content, sizeof(content))));
mcs_send_dpu(reason);
s_free(s);
}