00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "rdesktop.h"
00022
00023 uint16 mcs_userid;
00024
00025
00026 static BOOL
00027 ber_parse_header(STREAM s, int tagval, unsigned int *length)
00028 {
00029 int tag, len;
00030
00031 if (tagval > 0xff)
00032 {
00033 in_uint16_be(s, tag);
00034 }
00035 else
00036 {
00037 in_uint8(s, tag)}
00038
00039 if (tag != tagval)
00040 {
00041 error("expected tag %d, got %d\n", tagval, tag);
00042 return False;
00043 }
00044
00045 in_uint8(s, len);
00046
00047 if (len & 0x80)
00048 {
00049 len &= ~0x80;
00050 *length = 0;
00051 while (len--)
00052 next_be(s, *length);
00053 }
00054 else
00055 *length = len;
00056
00057 return s_check(s);
00058 }
00059
00060
00061 static void
00062 ber_out_header(STREAM s, int tagval, int length)
00063 {
00064 if (tagval > 0xff)
00065 {
00066 out_uint16_be(s, tagval);
00067 }
00068 else
00069 {
00070 out_uint8(s, tagval);
00071 }
00072
00073 if (length >= 0x80)
00074 {
00075 out_uint8(s, 0x82);
00076 out_uint16_be(s, length);
00077 }
00078 else
00079 out_uint8(s, length);
00080 }
00081
00082
00083 static void
00084 ber_out_integer(STREAM s, int value)
00085 {
00086 ber_out_header(s, BER_TAG_INTEGER, 2);
00087 out_uint16_be(s, value);
00088 }
00089
00090
00091 static void
00092 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
00093 {
00094 ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
00095 ber_out_integer(s, max_channels);
00096 ber_out_integer(s, max_users);
00097 ber_out_integer(s, max_tokens);
00098 ber_out_integer(s, 1);
00099 ber_out_integer(s, 0);
00100 ber_out_integer(s, 1);
00101 ber_out_integer(s, max_pdusize);
00102 ber_out_integer(s, 2);
00103 }
00104
00105
00106 static BOOL
00107 mcs_parse_domain_params(STREAM s)
00108 {
00109 unsigned int length;
00110
00111 ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
00112 in_uint8s(s, length);
00113
00114 return s_check(s);
00115 }
00116
00117
00118 static void
00119 mcs_send_connect_initial(STREAM mcs_data)
00120 {
00121 int datalen = mcs_data->end - mcs_data->data;
00122 int length = 7 + 3 * 34 + 4 + datalen;
00123 STREAM s;
00124
00125 s = iso_init(length + 5);
00126
00127 ber_out_header(s, MCS_CONNECT_INITIAL, length);
00128 ber_out_header(s, BER_TAG_OCTET_STRING, 0);
00129 ber_out_header(s, BER_TAG_OCTET_STRING, 0);
00130
00131 ber_out_header(s, BER_TAG_BOOLEAN, 1);
00132 out_uint8(s, 0xff);
00133
00134 mcs_out_domain_params(s, 2, 2, 0, 0xffff);
00135 mcs_out_domain_params(s, 1, 1, 1, 0x420);
00136 mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff);
00137
00138 ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
00139 out_uint8p(s, mcs_data->data, datalen);
00140
00141 s_mark_end(s);
00142 iso_send(s);
00143 }
00144
00145
00146 static BOOL
00147 mcs_recv_connect_response(STREAM mcs_data)
00148 {
00149 uint8 result;
00150 unsigned int length;
00151 STREAM s;
00152
00153 s = iso_recv();
00154 if (s == NULL)
00155 return False;
00156
00157 ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
00158
00159 ber_parse_header(s, BER_TAG_RESULT, &length);
00160 in_uint8(s, result);
00161 if (result != 0)
00162 {
00163 error("MCS connect: %d\n", result);
00164 return False;
00165 }
00166
00167 ber_parse_header(s, BER_TAG_INTEGER, &length);
00168 in_uint8s(s, length);
00169 mcs_parse_domain_params(s);
00170
00171 ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
00172 if (length > mcs_data->size)
00173 {
00174 error("MCS data length %d\n", length);
00175 length = mcs_data->size;
00176 }
00177
00178 in_uint8a(s, mcs_data->data, length);
00179 mcs_data->p = mcs_data->data;
00180 mcs_data->end = mcs_data->data + length;
00181
00182 return s_check_end(s);
00183 }
00184
00185
00186 static void
00187 mcs_send_edrq(void)
00188 {
00189 STREAM s;
00190
00191 s = iso_init(5);
00192
00193 out_uint8(s, (MCS_EDRQ << 2));
00194 out_uint16_be(s, 1);
00195 out_uint16_be(s, 1);
00196
00197 s_mark_end(s);
00198 iso_send(s);
00199 }
00200
00201
00202 static void
00203 mcs_send_aurq(void)
00204 {
00205 STREAM s;
00206
00207 s = iso_init(1);
00208
00209 out_uint8(s, (MCS_AURQ << 2));
00210
00211 s_mark_end(s);
00212 iso_send(s);
00213 }
00214
00215
00216 static BOOL
00217 mcs_recv_aucf(uint16 * mcs_userid)
00218 {
00219 uint8 opcode, result;
00220 STREAM s;
00221
00222 s = iso_recv();
00223 if (s == NULL)
00224 return False;
00225
00226 in_uint8(s, opcode);
00227 if ((opcode >> 2) != MCS_AUCF)
00228 {
00229 error("expected AUcf, got %d\n", opcode);
00230 return False;
00231 }
00232
00233 in_uint8(s, result);
00234 if (result != 0)
00235 {
00236 error("AUrq: %d\n", result);
00237 return False;
00238 }
00239
00240 if (opcode & 2)
00241 in_uint16_be(s, *mcs_userid);
00242
00243 return s_check_end(s);
00244 }
00245
00246
00247 static void
00248 mcs_send_cjrq(uint16 chanid)
00249 {
00250 STREAM s;
00251
00252 s = iso_init(5);
00253
00254 out_uint8(s, (MCS_CJRQ << 2));
00255 out_uint16_be(s, mcs_userid);
00256 out_uint16_be(s, chanid);
00257
00258 s_mark_end(s);
00259 iso_send(s);
00260 }
00261
00262
00263 static BOOL
00264 mcs_recv_cjcf(void)
00265 {
00266 uint8 opcode, result;
00267 STREAM s;
00268
00269 s = iso_recv();
00270 if (s == NULL)
00271 return False;
00272
00273 in_uint8(s, opcode);
00274 if ((opcode >> 2) != MCS_CJCF)
00275 {
00276 error("expected CJcf, got %d\n", opcode);
00277 return False;
00278 }
00279
00280 in_uint8(s, result);
00281 if (result != 0)
00282 {
00283 error("CJrq: %d\n", result);
00284 return False;
00285 }
00286
00287 in_uint8s(s, 4);
00288 if (opcode & 2)
00289 in_uint8s(s, 2);
00290
00291 return s_check_end(s);
00292 }
00293
00294
00295 STREAM
00296 mcs_init(int length)
00297 {
00298 STREAM s;
00299
00300 s = iso_init(length + 8);
00301 s_push_layer(s, mcs_hdr, 8);
00302
00303 return s;
00304 }
00305
00306
00307 void
00308 mcs_send(STREAM s)
00309 {
00310 uint16 length;
00311
00312 s_pop_layer(s, mcs_hdr);
00313 length = s->end - s->p - 8;
00314 length |= 0x8000;
00315
00316 out_uint8(s, (MCS_SDRQ << 2));
00317 out_uint16_be(s, mcs_userid);
00318 out_uint16_be(s, MCS_GLOBAL_CHANNEL);
00319 out_uint8(s, 0x70);
00320 out_uint16_be(s, length);
00321
00322 iso_send(s);
00323 }
00324
00325
00326 STREAM
00327 mcs_recv(void)
00328 {
00329 uint8 opcode, appid, length;
00330 STREAM s;
00331
00332 s = iso_recv();
00333 if (s == NULL)
00334 return NULL;
00335
00336 in_uint8(s, opcode);
00337 appid = opcode >> 2;
00338 if (appid != MCS_SDIN)
00339 {
00340 if (appid != MCS_DPUM)
00341 {
00342 error("expected data, got %d\n", opcode);
00343 }
00344 return NULL;
00345 }
00346
00347 in_uint8s(s, 5);
00348 in_uint8(s, length);
00349 if (length & 0x80)
00350 in_uint8s(s, 1);
00351
00352 return s;
00353 }
00354
00355
00356 BOOL
00357 mcs_connect(char *server, STREAM mcs_data)
00358 {
00359 if (!iso_connect(server))
00360 {
00361 return False;
00362 }
00363
00364 mcs_send_connect_initial(mcs_data);
00365 if (!mcs_recv_connect_response(mcs_data))
00366 goto error;
00367
00368 mcs_send_edrq();
00369
00370 mcs_send_aurq();
00371 if (!mcs_recv_aucf(&mcs_userid))
00372 goto error;
00373
00374 mcs_send_cjrq(mcs_userid + 1001);
00375 if (!mcs_recv_cjcf())
00376 goto error;
00377
00378 mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
00379 if (!mcs_recv_cjcf())
00380 goto error;
00381
00382 return True;
00383
00384 error:
00385 iso_disconnect();
00386 return False;
00387 }
00388
00389
00390 void
00391 mcs_disconnect(void)
00392 {
00393 iso_disconnect();
00394 }