ReactOS  0.4.14-dev-317-g96040ec
mcs.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 8 -*-
2  rdesktop: A Remote Desktop Protocol client.
3  Protocol services - Multipoint Communications Service
4  Copyright (C) Matthew Chapman 1999-2005
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License along
17  with this program; if not, write to the Free Software Foundation, Inc.,
18  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "rdesktop.h"
22 
23 /* Parse an ASN.1 BER header */
24 static BOOL
25 ber_parse_header(STREAM s, int tagval, int *length)
26 {
27  int tag, len;
28 
29  if (tagval > 0xff)
30  {
31  in_uint16_be(s, tag);
32  }
33  else
34  {
35  in_uint8(s, tag)}
36 
37  if (tag != tagval)
38  {
39  error("expected tag %d, got %d\n", tagval, tag);
40  return False;
41  }
42 
43  in_uint8(s, len);
44 
45  if (len & 0x80)
46  {
47  len &= ~0x80;
48  *length = 0;
49  while (len--)
50  next_be(s, *length);
51  }
52  else
53  *length = len;
54 
55  return s_check(s);
56 }
57 
58 /* Output an ASN.1 BER header */
59 static void
60 ber_out_header(STREAM s, int tagval, int length)
61 {
62  if (tagval > 0xff)
63  {
64  out_uint16_be(s, tagval);
65  }
66  else
67  {
68  out_uint8(s, tagval);
69  }
70 
71  if (length >= 0x80)
72  {
73  out_uint8(s, 0x82);
75  }
76  else
77  out_uint8(s, length);
78 }
79 
80 /* Output an ASN.1 BER integer */
81 static void
83 {
86 }
87 
88 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
89 static void
90 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
91 {
93  ber_out_integer(s, max_channels);
94  ber_out_integer(s, max_users);
95  ber_out_integer(s, max_tokens);
96  ber_out_integer(s, 1); /* num_priorities */
97  ber_out_integer(s, 0); /* min_throughput */
98  ber_out_integer(s, 1); /* max_height */
99  ber_out_integer(s, max_pdusize);
100  ber_out_integer(s, 2); /* ver_protocol */
101 }
102 
103 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
104 static BOOL
106 {
107  int length;
108 
110  in_uint8s(s, length);
111 
112  return s_check(s);
113 }
114 
115 /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
116 static BOOL
118 {
119  int datalen = (uint16)(mcs_data->end - mcs_data->data);
120  int length = 9 + 3 * 34 + 4 + datalen;
121  STREAM s;
122 
123  s = iso_init(This, length + 5);
124 
125  if(s == NULL)
126  return False;
127 
129  ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* calling domain */
130  out_uint8(s, 1);
131  ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* called domain */
132  out_uint8(s, 1);
133 
135  out_uint8(s, 0xff); /* upward flag */
136 
137  mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */
138  mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */
139  mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
140 
142  out_uint8p(s, mcs_data->data, datalen);
143 
144  s_mark_end(s);
145  return iso_send(This, s);
146 }
147 
148 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
149 static BOOL
151 {
152  uint8 result;
153  int length;
154  STREAM s;
155 
156  s = iso_recv(This, NULL);
157  if (s == NULL)
158  return False;
159 
161 
163  in_uint8(s, result);
164  if (result != 0)
165  {
166  error("MCS connect: %d\n", result);
167  return False;
168  }
169 
171  in_uint8s(s, length); /* connect id */
173 
175 
177  /*
178  if (length > mcs_data->size)
179  {
180  error("MCS data length %d, expected %d\n", length,
181  mcs_data->size);
182  length = mcs_data->size;
183  }
184 
185  in_uint8a(s, mcs_data->data, length);
186  mcs_data->p = mcs_data->data;
187  mcs_data->end = mcs_data->data + length;
188  */
189  return s_check_end(s);
190 }
191 
192 /* Send an EDrq message (ASN.1 PER) */
193 static BOOL
195 {
196  STREAM s;
197 
198  s = iso_init(This, 5);
199 
200  if(s == NULL)
201  return False;
202 
203  out_uint8(s, (MCS_EDRQ << 2));
204  out_uint16_be(s, 1); /* height */
205  out_uint16_be(s, 1); /* interval */
206 
207  s_mark_end(s);
208  return iso_send(This, s);
209 }
210 
211 /* Send an AUrq message (ASN.1 PER) */
212 static BOOL
214 {
215  STREAM s;
216 
217  s = iso_init(This, 1);
218 
219  if(s == NULL)
220  return False;
221 
222  out_uint8(s, (MCS_AURQ << 2));
223 
224  s_mark_end(s);
225  return iso_send(This, s);
226 }
227 
228 /* Expect a AUcf message (ASN.1 PER) */
229 static BOOL
231 {
232  uint8 opcode, result;
233  STREAM s;
234 
235  s = iso_recv(This, NULL);
236  if (s == NULL)
237  return False;
238 
239  in_uint8(s, opcode);
240  if ((opcode >> 2) != MCS_AUCF)
241  {
242  error("expected AUcf, got %d\n", opcode);
243  return False;
244  }
245 
246  in_uint8(s, result);
247  if (result != 0)
248  {
249  error("AUrq: %d\n", result);
250  return False;
251  }
252 
253  if (opcode & 2)
254  in_uint16_be(s, *mcs_userid);
255 
256  return s_check_end(s);
257 }
258 
259 /* Send a CJrq message (ASN.1 PER) */
260 static BOOL
262 {
263  STREAM s;
264 
265  DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
266 
267  s = iso_init(This, 5);
268 
269  if(s == NULL)
270  return False;
271 
272  out_uint8(s, (MCS_CJRQ << 2));
273  out_uint16_be(s, This->mcs_userid);
274  out_uint16_be(s, chanid);
275 
276  s_mark_end(s);
277  return iso_send(This, s);
278 }
279 
280 /* Expect a CJcf message (ASN.1 PER) */
281 static BOOL
283 {
284  uint8 opcode, result;
285  STREAM s;
286 
287  s = iso_recv(This, NULL);
288  if (s == NULL)
289  return False;
290 
291  in_uint8(s, opcode);
292  if ((opcode >> 2) != MCS_CJCF)
293  {
294  error("expected CJcf, got %d\n", opcode);
295  return False;
296  }
297 
298  in_uint8(s, result);
299  if (result != 0)
300  {
301  error("CJrq: %d\n", result);
302  return False;
303  }
304 
305  in_uint8s(s, 4); /* mcs_userid, req_chanid */
306  if (opcode & 2)
307  in_uint8s(s, 2); /* join_chanid */
308 
309  return s_check_end(s);
310 }
311 
312 /* Initialise an MCS transport data packet */
313 STREAM
315 {
316  STREAM s;
317 
318  s = iso_init(This, length + 8);
319 
320  if(s == NULL)
321  return NULL;
322 
323  s_push_layer(s, mcs_hdr, 8);
324 
325  return s;
326 }
327 
328 /* Send an MCS transport data packet to a specific channel */
329 BOOL
331 {
332  uint16 length;
333 
334  s_pop_layer(s, mcs_hdr);
335  length = (uint16)(s->end - s->p - 8);
336  length |= 0x8000;
337 
338  out_uint8(s, (MCS_SDRQ << 2));
339  out_uint16_be(s, This->mcs_userid);
340  out_uint16_be(s, channel);
341  out_uint8(s, 0x70); /* flags */
343 
344  return iso_send(This, s);
345 }
346 
347 /* Send an MCS transport data packet to the global channel */
348 BOOL
350 {
352 }
353 
354 /* Receive an MCS transport data packet */
355 STREAM
356 mcs_recv(RDPCLIENT * This, uint16 * channel, uint8 * rdpver)
357 {
358  uint8 opcode, appid, length;
359  STREAM s;
360 
361  s = iso_recv(This, rdpver);
362  if (s == NULL)
363  return NULL;
364  if (rdpver != NULL)
365  if (*rdpver != 3)
366  return s;
367  in_uint8(s, opcode);
368  appid = opcode >> 2;
369  if (appid != MCS_SDIN)
370  {
371  if (appid != MCS_DPUM)
372  {
373  error("expected data, got %d\n", opcode);
374  }
375  return NULL;
376  }
377  in_uint8s(s, 2); /* userid */
378  in_uint16_be(s, *channel);
379  in_uint8s(s, 1); /* flags */
380  in_uint8(s, length);
381  if (length & 0x80)
382  in_uint8s(s, 1); /* second byte of length */
383  return s;
384 }
385 
386 /* Establish a connection up to the MCS layer */
387 BOOL
388 mcs_connect(RDPCLIENT * This, char *server, char * cookie, STREAM mcs_data)
389 {
390  unsigned int i;
391 
392  if (!iso_connect(This, server, cookie))
393  return False;
394 
395  if (!mcs_send_connect_initial(This, mcs_data) || !mcs_recv_connect_response(This, mcs_data))
396  goto error;
397 
399  goto error;
400 
401  if (!mcs_recv_aucf(This, &This->mcs_userid))
402  goto error;
403 
404  if (!mcs_send_cjrq(This, This->mcs_userid + MCS_USERCHANNEL_BASE) || !mcs_recv_cjcf(This))
405  goto error;
406 
408  goto error;
409 
410  for (i = 0; i < This->num_channels; i++)
411  {
413  goto error;
414  }
415  return True;
416 
417  error:
419  return False;
420 }
421 
422 /* Establish a connection up to the MCS layer */
423 BOOL
424 mcs_reconnect(RDPCLIENT * This, char *server, char *cookie, STREAM mcs_data)
425 {
426  unsigned int i;
427 
428  if (!iso_reconnect(This, server, cookie))
429  return False;
430 
431  if (!mcs_send_connect_initial(This, mcs_data) || !mcs_recv_connect_response(This, mcs_data))
432  goto error;
433 
435  goto error;
436 
437  if (!mcs_recv_aucf(This, &This->mcs_userid))
438  goto error;
439 
440  if (!mcs_send_cjrq(This, This->mcs_userid + MCS_USERCHANNEL_BASE) || !mcs_recv_cjcf(This))
441  goto error;
442 
444  goto error;
445 
446  for (i = 0; i < This->num_channels; i++)
447  {
449  goto error;
450  }
451  return True;
452 
453  error:
455  return False;
456 }
457 
458 /* Disconnect from the MCS layer */
459 void
461 {
463 }
464 
465 /* reset the state of the mcs layer */
466 void
468 {
469  This->mcs_userid = 0;
471 }
static BOOL mcs_send_edrq(RDPCLIENT *This)
Definition: mcs.c:194
#define out_uint8p(s, v, n)
Definition: parse.h:93
static rfbScreenInfoPtr server
Definition: vnc.c:74
#define error(str)
Definition: mkdosfs.c:1605
void mcs_send_to_channel(STREAM s, uint16 channel)
Definition: mcs.c:254
#define MCS_CONNECT_INITIAL
Definition: constants.h:74
static void mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
Definition: mcs.c:90
Definition: ecma_167.h:138
unsigned char * data
Definition: parse.h:26
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
static BOOL mcs_send_connect_initial(RDPCLIENT *This, STREAM mcs_data)
Definition: mcs.c:117
BOOL iso_reconnect(RDPCLIENT *This, char *server, char *cookie)
Definition: iso.c:204
#define MCS_TAG_DOMAIN_PARAMS
Definition: constants.h:85
#define s_check(s)
Definition: parse.h:42
#define MCS_GLOBAL_CHANNEL
Definition: constants.h:87
static BOOL mcs_send_aurq(RDPCLIENT *This)
Definition: mcs.c:213
static BOOL mcs_parse_domain_params(STREAM s)
Definition: mcs.c:105
#define out_uint8(s, v)
Definition: parse.h:92
void mcs_reset_state(void)
Definition: mcs.c:363
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
void iso_disconnect(void)
Definition: iso.c:362
unsigned int BOOL
Definition: ntddk_ex.h:94
#define s_pop_layer(s, h)
Definition: parse.h:40
static BOOL mcs_send_cjrq(RDPCLIENT *This, uint16 chanid)
Definition: mcs.c:261
char * appid
Definition: mkisofs.c:161
smooth NULL
Definition: ftsmooth.c:416
#define in_uint8s(s, n)
Definition: parse.h:91
STREAM iso_init(int length)
Definition: iso.c:150
#define s_check_end(s)
Definition: parse.h:44
static void ber_out_header(STREAM s, int tagval, int length)
Definition: mcs.c:60
#define True
Definition: types.h:24
#define False
Definition: types.h:25
#define MCS_USERCHANNEL_BASE
Definition: constants.h:88
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
STREAM iso_recv(uint8 *rdpver)
Definition: iso.c:182
void iso_send(STREAM s)
Definition: iso.c:162
unsigned char * end
Definition: parse.h:25
unsigned char uint8
Definition: types.h:28
static void ber_out_integer(STREAM s, int value)
Definition: mcs.c:82
#define BER_TAG_INTEGER
Definition: constants.h:78
static BOOL mcs_recv_aucf(RDPCLIENT *This, uint16 *mcs_userid)
Definition: mcs.c:230
STREAM mcs_init(int length)
Definition: mcs.c:242
RD_BOOL iso_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect, uint32 *selected_protocol)
Definition: iso.c:203
Definition: parse.h:22
#define MCS_CONNECT_RESPONSE
Definition: constants.h:75
STREAM mcs_recv(uint16 *channel, uint8 *rdpver)
Definition: mcs.c:280
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
void sec_process_mcs_data(STREAM s)
Definition: secure.c:856
#define BER_TAG_RESULT
Definition: constants.h:80
static BOOL ber_parse_header(STREAM s, int tagval, int *length)
Definition: mcs.c:25
#define s_push_layer(s, h, n)
Definition: parse.h:39
#define BER_TAG_OCTET_STRING
Definition: constants.h:79
#define DEBUG_RDP5(args)
Definition: rdesktop.h:141
static BOOL mcs_recv_cjcf(RDPCLIENT *This)
Definition: mcs.c:282
void iso_reset_state(void)
Definition: iso.c:370
unsigned short uint16
Definition: types.h:30
#define in_uint8(s, v)
Definition: parse.h:88
#define next_be(s, v)
Definition: parse.h:97
#define out_uint16_be(s, v)
Definition: parse.h:77
static BOOL mcs_recv_connect_response(RDPCLIENT *This, STREAM mcs_data)
Definition: mcs.c:150
void mcs_send(STREAM s)
Definition: mcs.c:273
#define BER_TAG_BOOLEAN
Definition: constants.h:77
#define s_mark_end(s)
Definition: parse.h:41
BOOL mcs_reconnect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:424
BOOL mcs_connect(RDPCLIENT *This, char *server, char *cookie, STREAM mcs_data)
Definition: mcs.c:388
GLuint64EXT * result
Definition: glext.h:11304
void mcs_disconnect(void)
Definition: mcs.c:356
#define in_uint16_be(s, v)
Definition: parse.h:75
char * tag
Definition: main.c:59