Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmcs.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*- 00002 rdesktop: A Remote Desktop Protocol client. 00003 Protocol services - Multipoint Communications Service 00004 Copyright (C) Matthew Chapman 1999-2005 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License along 00017 with this program; if not, write to the Free Software Foundation, Inc., 00018 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 00021 #include <precomp.h> 00022 00023 uint16 g_mcs_userid; 00024 extern VCHANNEL g_channels[]; 00025 extern unsigned int g_num_channels; 00026 00027 /* Parse an ASN.1 BER header */ 00028 static BOOL 00029 ber_parse_header(STREAM s, int tagval, int *length) 00030 { 00031 int tag, len; 00032 00033 if (tagval > 0xff) 00034 { 00035 in_uint16_be(s, tag); 00036 } 00037 else 00038 { 00039 in_uint8(s, tag)} 00040 00041 if (tag != tagval) 00042 { 00043 error("expected tag %d, got %d\n", tagval, tag); 00044 return False; 00045 } 00046 00047 in_uint8(s, len); 00048 00049 if (len & 0x80) 00050 { 00051 len &= ~0x80; 00052 *length = 0; 00053 while (len--) 00054 next_be(s, *length); 00055 } 00056 else 00057 *length = len; 00058 00059 return s_check(s); 00060 } 00061 00062 /* Output an ASN.1 BER header */ 00063 static void 00064 ber_out_header(STREAM s, int tagval, int length) 00065 { 00066 if (tagval > 0xff) 00067 { 00068 out_uint16_be(s, tagval); 00069 } 00070 else 00071 { 00072 out_uint8(s, tagval); 00073 } 00074 00075 if (length >= 0x80) 00076 { 00077 out_uint8(s, 0x82); 00078 out_uint16_be(s, length); 00079 } 00080 else 00081 out_uint8(s, length); 00082 } 00083 00084 /* Output an ASN.1 BER integer */ 00085 static void 00086 ber_out_integer(STREAM s, int value) 00087 { 00088 ber_out_header(s, BER_TAG_INTEGER, 2); 00089 out_uint16_be(s, value); 00090 } 00091 00092 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */ 00093 static void 00094 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize) 00095 { 00096 ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32); 00097 ber_out_integer(s, max_channels); 00098 ber_out_integer(s, max_users); 00099 ber_out_integer(s, max_tokens); 00100 ber_out_integer(s, 1); /* num_priorities */ 00101 ber_out_integer(s, 0); /* min_throughput */ 00102 ber_out_integer(s, 1); /* max_height */ 00103 ber_out_integer(s, max_pdusize); 00104 ber_out_integer(s, 2); /* ver_protocol */ 00105 } 00106 00107 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */ 00108 static BOOL 00109 mcs_parse_domain_params(STREAM s) 00110 { 00111 int length; 00112 00113 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length); 00114 in_uint8s(s, length); 00115 00116 return s_check(s); 00117 } 00118 00119 /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */ 00120 static void 00121 mcs_send_connect_initial(STREAM mcs_data) 00122 { 00123 int datalen = mcs_data->end - mcs_data->data; 00124 int length = 9 + 3 * 34 + 4 + datalen; 00125 STREAM s; 00126 00127 s = iso_init(length + 5); 00128 00129 ber_out_header(s, MCS_CONNECT_INITIAL, length); 00130 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* calling domain */ 00131 out_uint8(s, 1); 00132 ber_out_header(s, BER_TAG_OCTET_STRING, 1); /* called domain */ 00133 out_uint8(s, 1); 00134 00135 ber_out_header(s, BER_TAG_BOOLEAN, 1); 00136 out_uint8(s, 0xff); /* upward flag */ 00137 00138 mcs_out_domain_params(s, 34, 2, 0, 0xffff); /* target params */ 00139 mcs_out_domain_params(s, 1, 1, 1, 0x420); /* min params */ 00140 mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */ 00141 00142 ber_out_header(s, BER_TAG_OCTET_STRING, datalen); 00143 out_uint8p(s, mcs_data->data, datalen); 00144 00145 s_mark_end(s); 00146 iso_send(s); 00147 } 00148 00149 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */ 00150 static BOOL 00151 mcs_recv_connect_response(STREAM mcs_data) 00152 { 00153 uint8 result; 00154 int length; 00155 STREAM s; 00156 00157 s = iso_recv(NULL); 00158 if (s == NULL) 00159 return False; 00160 00161 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length); 00162 00163 ber_parse_header(s, BER_TAG_RESULT, &length); 00164 in_uint8(s, result); 00165 if (result != 0) 00166 { 00167 error("MCS connect: %d\n", result); 00168 return False; 00169 } 00170 00171 ber_parse_header(s, BER_TAG_INTEGER, &length); 00172 in_uint8s(s, length); /* connect id */ 00173 mcs_parse_domain_params(s); 00174 00175 ber_parse_header(s, BER_TAG_OCTET_STRING, &length); 00176 00177 sec_process_mcs_data(s); 00178 /* 00179 if (length > mcs_data->size) 00180 { 00181 error("MCS data length %d, expected %d\n", length, 00182 mcs_data->size); 00183 length = mcs_data->size; 00184 } 00185 00186 in_uint8a(s, mcs_data->data, length); 00187 mcs_data->p = mcs_data->data; 00188 mcs_data->end = mcs_data->data + length; 00189 */ 00190 return s_check_end(s); 00191 } 00192 00193 /* Send an EDrq message (ASN.1 PER) */ 00194 static void 00195 mcs_send_edrq(void) 00196 { 00197 STREAM s; 00198 00199 s = iso_init(5); 00200 00201 out_uint8(s, (MCS_EDRQ << 2)); 00202 out_uint16_be(s, 1); /* height */ 00203 out_uint16_be(s, 1); /* interval */ 00204 00205 s_mark_end(s); 00206 iso_send(s); 00207 } 00208 00209 /* Send an AUrq message (ASN.1 PER) */ 00210 static void 00211 mcs_send_aurq(void) 00212 { 00213 STREAM s; 00214 00215 s = iso_init(1); 00216 00217 out_uint8(s, (MCS_AURQ << 2)); 00218 00219 s_mark_end(s); 00220 iso_send(s); 00221 } 00222 00223 /* Expect a AUcf message (ASN.1 PER) */ 00224 static BOOL 00225 mcs_recv_aucf(uint16 * mcs_userid) 00226 { 00227 uint8 opcode, result; 00228 STREAM s; 00229 00230 s = iso_recv(NULL); 00231 if (s == NULL) 00232 return False; 00233 00234 in_uint8(s, opcode); 00235 if ((opcode >> 2) != MCS_AUCF) 00236 { 00237 error("expected AUcf, got %d\n", opcode); 00238 return False; 00239 } 00240 00241 in_uint8(s, result); 00242 if (result != 0) 00243 { 00244 error("AUrq: %d\n", result); 00245 return False; 00246 } 00247 00248 if (opcode & 2) 00249 in_uint16_be(s, *mcs_userid); 00250 00251 return s_check_end(s); 00252 } 00253 00254 /* Send a CJrq message (ASN.1 PER) */ 00255 static void 00256 mcs_send_cjrq(uint16 chanid) 00257 { 00258 STREAM s; 00259 00260 DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid)); 00261 00262 s = iso_init(5); 00263 00264 out_uint8(s, (MCS_CJRQ << 2)); 00265 out_uint16_be(s, g_mcs_userid); 00266 out_uint16_be(s, chanid); 00267 00268 s_mark_end(s); 00269 iso_send(s); 00270 } 00271 00272 /* Expect a CJcf message (ASN.1 PER) */ 00273 static BOOL 00274 mcs_recv_cjcf(void) 00275 { 00276 uint8 opcode, result; 00277 STREAM s; 00278 00279 s = iso_recv(NULL); 00280 if (s == NULL) 00281 return False; 00282 00283 in_uint8(s, opcode); 00284 if ((opcode >> 2) != MCS_CJCF) 00285 { 00286 error("expected CJcf, got %d\n", opcode); 00287 return False; 00288 } 00289 00290 in_uint8(s, result); 00291 if (result != 0) 00292 { 00293 error("CJrq: %d\n", result); 00294 return False; 00295 } 00296 00297 in_uint8s(s, 4); /* mcs_userid, req_chanid */ 00298 if (opcode & 2) 00299 in_uint8s(s, 2); /* join_chanid */ 00300 00301 return s_check_end(s); 00302 } 00303 00304 /* Initialise an MCS transport data packet */ 00305 STREAM 00306 mcs_init(int length) 00307 { 00308 STREAM s; 00309 00310 s = iso_init(length + 8); 00311 s_push_layer(s, mcs_hdr, 8); 00312 00313 return s; 00314 } 00315 00316 /* Send an MCS transport data packet to a specific channel */ 00317 void 00318 mcs_send_to_channel(STREAM s, uint16 channel) 00319 { 00320 uint16 length; 00321 00322 s_pop_layer(s, mcs_hdr); 00323 length = s->end - s->p - 8; 00324 length |= 0x8000; 00325 00326 out_uint8(s, (MCS_SDRQ << 2)); 00327 out_uint16_be(s, g_mcs_userid); 00328 out_uint16_be(s, channel); 00329 out_uint8(s, 0x70); /* flags */ 00330 out_uint16_be(s, length); 00331 00332 iso_send(s); 00333 } 00334 00335 /* Send an MCS transport data packet to the global channel */ 00336 void 00337 mcs_send(STREAM s) 00338 { 00339 mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL); 00340 } 00341 00342 /* Receive an MCS transport data packet */ 00343 STREAM 00344 mcs_recv(uint16 * channel, uint8 * rdpver) 00345 { 00346 uint8 opcode, appid, length; 00347 STREAM s; 00348 00349 s = iso_recv(rdpver); 00350 if (s == NULL) 00351 return NULL; 00352 if (rdpver != NULL) 00353 if (*rdpver != 3) 00354 return s; 00355 in_uint8(s, opcode); 00356 appid = opcode >> 2; 00357 if (appid != MCS_SDIN) 00358 { 00359 if (appid != MCS_DPUM) 00360 { 00361 error("expected data, got %d\n", opcode); 00362 } 00363 return NULL; 00364 } 00365 in_uint8s(s, 2); /* userid */ 00366 in_uint16_be(s, *channel); 00367 in_uint8s(s, 1); /* flags */ 00368 in_uint8(s, length); 00369 if (length & 0x80) 00370 in_uint8s(s, 1); /* second byte of length */ 00371 return s; 00372 } 00373 00374 /* Establish a connection up to the MCS layer */ 00375 BOOL 00376 mcs_connect(char *server, STREAM mcs_data, char *username) 00377 { 00378 unsigned int i; 00379 00380 if (!iso_connect(server, username)) 00381 return False; 00382 00383 mcs_send_connect_initial(mcs_data); 00384 if (!mcs_recv_connect_response(mcs_data)) 00385 goto error; 00386 00387 mcs_send_edrq(); 00388 00389 mcs_send_aurq(); 00390 if (!mcs_recv_aucf(&g_mcs_userid)) 00391 goto error; 00392 00393 mcs_send_cjrq((uint16) (g_mcs_userid + MCS_USERCHANNEL_BASE)); 00394 00395 if (!mcs_recv_cjcf()) 00396 goto error; 00397 00398 mcs_send_cjrq(MCS_GLOBAL_CHANNEL); 00399 if (!mcs_recv_cjcf()) 00400 goto error; 00401 00402 for (i = 0; i < g_num_channels; i++) 00403 { 00404 mcs_send_cjrq(g_channels[i].mcs_id); 00405 if (!mcs_recv_cjcf()) 00406 goto error; 00407 } 00408 return True; 00409 00410 error: 00411 iso_disconnect(); 00412 return False; 00413 } 00414 00415 /* Establish a connection up to the MCS layer */ 00416 BOOL 00417 mcs_reconnect(char *server, STREAM mcs_data) 00418 { 00419 unsigned int i; 00420 00421 if (!iso_reconnect(server)) 00422 return False; 00423 00424 mcs_send_connect_initial(mcs_data); 00425 if (!mcs_recv_connect_response(mcs_data)) 00426 goto error; 00427 00428 mcs_send_edrq(); 00429 00430 mcs_send_aurq(); 00431 if (!mcs_recv_aucf(&g_mcs_userid)) 00432 goto error; 00433 00434 mcs_send_cjrq((uint16) (g_mcs_userid + MCS_USERCHANNEL_BASE)); 00435 00436 if (!mcs_recv_cjcf()) 00437 goto error; 00438 00439 mcs_send_cjrq(MCS_GLOBAL_CHANNEL); 00440 if (!mcs_recv_cjcf()) 00441 goto error; 00442 00443 for (i = 0; i < g_num_channels; i++) 00444 { 00445 mcs_send_cjrq(g_channels[i].mcs_id); 00446 if (!mcs_recv_cjcf()) 00447 goto error; 00448 } 00449 return True; 00450 00451 error: 00452 iso_disconnect(); 00453 return False; 00454 } 00455 00456 /* Disconnect from the MCS layer */ 00457 void 00458 mcs_disconnect(void) 00459 { 00460 iso_disconnect(); 00461 } 00462 00463 /* reset the state of the mcs layer */ 00464 void 00465 mcs_reset_state(void) 00466 { 00467 g_mcs_userid = 0; 00468 iso_reset_state(); 00469 } Generated on Sat May 26 2012 04:16:05 for ReactOS by
1.7.6.1
|