⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcs.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
字号:
/* -*- c-basic-offset: 8 -*-   rdesktop: A Remote Desktop Protocol client.   Protocol services - Multipoint Communications Service   Copyright (C) Matthew Chapman 1999-2005      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "rdesktop.h"uint16 g_mcs_userid;extern VCHANNEL g_channels[];extern unsigned int g_num_channels;/* Parse an ASN.1 BER header */static BOOLber_parse_header(STREAM s, int tagval, int *length){	int tag, len;	if (tagval > 0xff)	{		in_uint16_be(s, tag);	}	else	{	in_uint8(s, tag)}	if (tag != tagval)	{		error("expected tag %d, got %d\n", tagval, tag);		return False;	}	in_uint8(s, len);	if (len & 0x80)	{		len &= ~0x80;		*length = 0;		while (len--)			next_be(s, *length);	}	else		*length = len;	return s_check(s);}/* Output an ASN.1 BER header */static voidber_out_header(STREAM s, int tagval, int length){	if (tagval > 0xff)	{		out_uint16_be(s, tagval);	}	else	{		out_uint8(s, tagval);	}	if (length >= 0x80)	{		out_uint8(s, 0x82);		out_uint16_be(s, length);	}	else		out_uint8(s, length);}/* Output an ASN.1 BER integer */static voidber_out_integer(STREAM s, int value){	ber_out_header(s, BER_TAG_INTEGER, 2);	out_uint16_be(s, value);}/* Output a DOMAIN_PARAMS structure (ASN.1 BER) */static voidmcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize){	ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);	ber_out_integer(s, max_channels);	ber_out_integer(s, max_users);	ber_out_integer(s, max_tokens);	ber_out_integer(s, 1);	/* num_priorities */	ber_out_integer(s, 0);	/* min_throughput */	ber_out_integer(s, 1);	/* max_height */	ber_out_integer(s, max_pdusize);	ber_out_integer(s, 2);	/* ver_protocol */}/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */static BOOLmcs_parse_domain_params(STREAM s){	int length;	ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);	in_uint8s(s, length);	return s_check(s);}/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */static voidmcs_send_connect_initial(STREAM mcs_data){	int datalen = mcs_data->end - mcs_data->data;	int length = 9 + 3 * 34 + 4 + datalen;	STREAM s;	s = iso_init(length + 5);	ber_out_header(s, MCS_CONNECT_INITIAL, length);	ber_out_header(s, BER_TAG_OCTET_STRING, 1);	/* calling domain */	out_uint8(s, 1);	ber_out_header(s, BER_TAG_OCTET_STRING, 1);	/* called domain */	out_uint8(s, 1);	ber_out_header(s, BER_TAG_BOOLEAN, 1);	out_uint8(s, 0xff);	/* upward flag */	mcs_out_domain_params(s, 34, 2, 0, 0xffff);	/* target params */	mcs_out_domain_params(s, 1, 1, 1, 0x420);	/* min params */	mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff);	/* max params */	ber_out_header(s, BER_TAG_OCTET_STRING, datalen);	out_uint8p(s, mcs_data->data, datalen);	s_mark_end(s);	iso_send(s);}/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */static BOOLmcs_recv_connect_response(STREAM mcs_data){	uint8 result;	int length;	STREAM s;	s = iso_recv(NULL);	if (s == NULL)		return False;	ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);	ber_parse_header(s, BER_TAG_RESULT, &length);	in_uint8(s, result);	if (result != 0)	{		error("MCS connect: %d\n", result);		return False;	}	ber_parse_header(s, BER_TAG_INTEGER, &length);	in_uint8s(s, length);	/* connect id */	mcs_parse_domain_params(s);	ber_parse_header(s, BER_TAG_OCTET_STRING, &length);	sec_process_mcs_data(s);	/*	   if (length > mcs_data->size)	   {	   error("MCS data length %d, expected %d\n", length,	   mcs_data->size);	   length = mcs_data->size;	   }	   in_uint8a(s, mcs_data->data, length);	   mcs_data->p = mcs_data->data;	   mcs_data->end = mcs_data->data + length;	 */	return s_check_end(s);}/* Send an EDrq message (ASN.1 PER) */static voidmcs_send_edrq(void){	STREAM s;	s = iso_init(5);	out_uint8(s, (MCS_EDRQ << 2));	out_uint16_be(s, 1);	/* height */	out_uint16_be(s, 1);	/* interval */	s_mark_end(s);	iso_send(s);}/* Send an AUrq message (ASN.1 PER) */static voidmcs_send_aurq(void){	STREAM s;	s = iso_init(1);	out_uint8(s, (MCS_AURQ << 2));	s_mark_end(s);	iso_send(s);}/* Expect a AUcf message (ASN.1 PER) */static BOOLmcs_recv_aucf(uint16 * mcs_userid){	uint8 opcode, result;	STREAM s;	s = iso_recv(NULL);	if (s == NULL)		return False;	in_uint8(s, opcode);	if ((opcode >> 2) != MCS_AUCF)	{		error("expected AUcf, got %d\n", opcode);		return False;	}	in_uint8(s, result);	if (result != 0)	{		error("AUrq: %d\n", result);		return False;	}	if (opcode & 2)		in_uint16_be(s, *mcs_userid);	return s_check_end(s);}/* Send a CJrq message (ASN.1 PER) */static voidmcs_send_cjrq(uint16 chanid){	STREAM s;	DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));	s = iso_init(5);	out_uint8(s, (MCS_CJRQ << 2));	out_uint16_be(s, g_mcs_userid);	out_uint16_be(s, chanid);	s_mark_end(s);	iso_send(s);}/* Expect a CJcf message (ASN.1 PER) */static BOOLmcs_recv_cjcf(void){	uint8 opcode, result;	STREAM s;	s = iso_recv(NULL);	if (s == NULL)		return False;	in_uint8(s, opcode);	if ((opcode >> 2) != MCS_CJCF)	{		error("expected CJcf, got %d\n", opcode);		return False;	}	in_uint8(s, result);	if (result != 0)	{		error("CJrq: %d\n", result);		return False;	}	in_uint8s(s, 4);	/* mcs_userid, req_chanid */	if (opcode & 2)		in_uint8s(s, 2);	/* join_chanid */	return s_check_end(s);}/* Initialise an MCS transport data packet */STREAMmcs_init(int length){	STREAM s;	s = iso_init(length + 8);	s_push_layer(s, mcs_hdr, 8);	return s;}/* Send an MCS transport data packet to a specific channel */voidmcs_send_to_channel(STREAM s, uint16 channel){	uint16 length;	s_pop_layer(s, mcs_hdr);	length = s->end - s->p - 8;	length |= 0x8000;	out_uint8(s, (MCS_SDRQ << 2));	out_uint16_be(s, g_mcs_userid);	out_uint16_be(s, channel);	out_uint8(s, 0x70);	/* flags */	out_uint16_be(s, length);	iso_send(s);}/* Send an MCS transport data packet to the global channel */voidmcs_send(STREAM s){	mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);}/* Receive an MCS transport data packet */STREAMmcs_recv(uint16 * channel, uint8 * rdpver){	uint8 opcode, appid, length;	STREAM s;	s = iso_recv(rdpver);	if (s == NULL)		return NULL;	if (rdpver != NULL)		if (*rdpver != 3)			return s;	in_uint8(s, opcode);	appid = opcode >> 2;	if (appid != MCS_SDIN)	{		if (appid != MCS_DPUM)		{			error("expected data, got %d\n", opcode);		}		return NULL;	}	in_uint8s(s, 2);	/* userid */	in_uint16_be(s, *channel);	in_uint8s(s, 1);	/* flags */	in_uint8(s, length);	if (length & 0x80)		in_uint8s(s, 1);	/* second byte of length */	return s;}/* Establish a connection up to the MCS layer */BOOLmcs_connect(char *server, STREAM mcs_data, char *username){	unsigned int i;	if (!iso_connect(server, username))		return False;	mcs_send_connect_initial(mcs_data);	if (!mcs_recv_connect_response(mcs_data))		goto error;	mcs_send_edrq();	mcs_send_aurq();	if (!mcs_recv_aucf(&g_mcs_userid))		goto error;	mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);	if (!mcs_recv_cjcf())		goto error;	mcs_send_cjrq(MCS_GLOBAL_CHANNEL);	if (!mcs_recv_cjcf())		goto error;	for (i = 0; i < g_num_channels; i++)	{		mcs_send_cjrq(g_channels[i].mcs_id);		if (!mcs_recv_cjcf())			goto error;	}	return True;      error:	iso_disconnect();	return False;}/* Establish a connection up to the MCS layer */BOOLmcs_reconnect(char *server, STREAM mcs_data){	unsigned int i;	if (!iso_reconnect(server))		return False;	mcs_send_connect_initial(mcs_data);	if (!mcs_recv_connect_response(mcs_data))		goto error;	mcs_send_edrq();	mcs_send_aurq();	if (!mcs_recv_aucf(&g_mcs_userid))		goto error;	mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);	if (!mcs_recv_cjcf())		goto error;	mcs_send_cjrq(MCS_GLOBAL_CHANNEL);	if (!mcs_recv_cjcf())		goto error;	for (i = 0; i < g_num_channels; i++)	{		mcs_send_cjrq(g_channels[i].mcs_id);		if (!mcs_recv_cjcf())			goto error;	}	return True;      error:	iso_disconnect();	return False;}/* Disconnect from the MCS layer */voidmcs_disconnect(void){	iso_disconnect();}/* reset the state of the mcs layer */voidmcs_reset_state(void){	g_mcs_userid = 0;	iso_reset_state();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -