/[rdesktop]/sourceforge.net/trunk/rdesktop/mcs.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/mcs.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 1365 by jsorg71, Thu Jan 4 05:39:39 2007 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - Multipoint Communications Service     Protocol services - Multipoint Communications Service
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2007
5      
6     This program is free software; you can redistribute it and/or modify     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     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     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include "rdesktop.h"
22    
23  /* Establish a connection up to the MCS layer */  uint16 g_mcs_userid;
24  HCONN mcs_connect(char *server)  extern VCHANNEL g_channels[];
25  {  extern unsigned int g_num_channels;
         HCONN conn;  
         MCS_CONNECT_RESPONSE mcr;  
         MCS_AUCF aucf;  
26    
27          if ((conn = iso_connect(server)) == NULL)  /* Parse an ASN.1 BER header */
28                  return NULL;  static BOOL
29    ber_parse_header(STREAM s, int tagval, int *length)
30          mcs_send_connect_initial(conn);  {
31          if (!iso_recv(conn) || !mcs_io_connect_response(&conn->in, &mcr))          int tag, len;
         {  
                 ERROR("MCS error, expected Connect-Response\n");  
                 iso_disconnect(conn);  
                 return NULL;  
         }  
32    
33          if (mcr.result != 0)          if (tagval > 0xff)
34          {          {
35                  ERROR("MCS-Connect-Initial failed, result %d\n", mcr.result);                  in_uint16_be(s, tag);
                 iso_disconnect(conn);  
                 return NULL;  
36          }          }
37            else
         mcs_send_edrq(conn);  
   
         mcs_send_aurq(conn);  
         if (!iso_recv(conn) || !mcs_io_aucf(&conn->in, &aucf))  
38          {          {
39                  ERROR("MCS error, expected AUcf\n");          in_uint8(s, tag)}
                 mcs_disconnect(conn);  
                 return NULL;  
         }  
40    
41          if (aucf.result != 0)          if (tag != tagval)
42          {          {
43                  ERROR("AUrq failed, result %d\n", mcr.result);                  error("expected tag %d, got %d\n", tagval, tag);
44                  mcs_disconnect(conn);                  return False;
                 return NULL;  
45          }          }
46    
47          conn->mcs_userid = aucf.userid;          in_uint8(s, len);
48    
49          if (!mcs_join_channel(conn, aucf.userid + 1001)          if (len & 0x80)
             || !mcs_join_channel(conn, MCS_GLOBAL_CHANNEL))  
50          {          {
51                  mcs_disconnect(conn);                  len &= ~0x80;
52                  return NULL;                  *length = 0;
53                    while (len--)
54                            next_be(s, *length);
55          }          }
56            else
57                    *length = len;
58    
59          return conn;          return s_check(s);
60  }  }
61    
62  BOOL mcs_join_channel(HCONN conn, uint16 chanid)  /* Output an ASN.1 BER header */
63    static void
64    ber_out_header(STREAM s, int tagval, int length)
65  {  {
66          MCS_CJCF cjcf;          if (tagval > 0xff)
   
         mcs_send_cjrq(conn, chanid);  
         if (!iso_recv(conn) || !mcs_io_cjcf(&conn->in, &cjcf))  
67          {          {
68                  ERROR("MCS error, expected CJcf\n");                  out_uint16_be(s, tagval);
                 return False;  
69          }          }
70            else
         if (cjcf.result != 0)  
71          {          {
72                  ERROR("CJrq failed, result %d\n", cjcf.result);                  out_uint8(s, tagval);
                 return False;  
73          }          }
74    
75          return True;          if (length >= 0x80)
76            {
77                    out_uint8(s, 0x82);
78                    out_uint16_be(s, length);
79            }
80            else
81                    out_uint8(s, length);
82  }  }
83    
84  /* Disconnect from the MCS layer */  /* Output an ASN.1 BER integer */
85  void mcs_disconnect(HCONN conn)  static void
86    ber_out_integer(STREAM s, int value)
87  {  {
88          /* Not complete */          ber_out_header(s, BER_TAG_INTEGER, 2);
89          iso_disconnect(conn);          out_uint16_be(s, value);
90  }  }
91    
92  /* Send a Connect-Initial message */  /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
93  void mcs_send_connect_initial(HCONN conn)  static void
94    mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
95  {  {
96          MCS_CONNECT_INITIAL mci;          ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
97            ber_out_integer(s, max_channels);
98          iso_init(conn);          ber_out_integer(s, max_users);
99          mcs_make_connect_initial(&mci);          ber_out_integer(s, max_tokens);
100          mcs_io_connect_initial(&conn->out, &mci);          ber_out_integer(s, 1);  /* num_priorities */
101          MARK_END(conn->out);          ber_out_integer(s, 0);  /* min_throughput */
102          iso_send(conn);          ber_out_integer(s, 1);  /* max_height */
103            ber_out_integer(s, max_pdusize);
104            ber_out_integer(s, 2);  /* ver_protocol */
105  }  }
106    
107  /* Send a EDrq message */  /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
108  void mcs_send_edrq(HCONN conn)  static BOOL
109    mcs_parse_domain_params(STREAM s)
110  {  {
111          MCS_EDRQ edrq;          int length;
112    
113          iso_init(conn);          ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
114          edrq.height = edrq.interval = 1;          in_uint8s(s, length);
115          mcs_io_edrq(&conn->out, &edrq);  
116          MARK_END(conn->out);          return s_check(s);
         iso_send(conn);  
117  }  }
118    
119  /* Send a AUrq message */  /* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
120  void mcs_send_aurq(HCONN conn)  static void
121    mcs_send_connect_initial(STREAM mcs_data)
122  {  {
123          MCS_AURQ aurq;          int datalen = mcs_data->end - mcs_data->data;
124            int length = 9 + 3 * 34 + 4 + datalen;
125            STREAM s;
126    
127          iso_init(conn);          s = iso_init(length + 5);
         mcs_io_aurq(&conn->out, &aurq);  
         MARK_END(conn->out);  
         iso_send(conn);  
 }  
128    
129  /* Send a CJrq message */          ber_out_header(s, MCS_CONNECT_INITIAL, length);
130  void mcs_send_cjrq(HCONN conn, uint16 chanid)          ber_out_header(s, BER_TAG_OCTET_STRING, 1);     /* calling domain */
131  {          out_uint8(s, 1);
132          MCS_CJRQ cjrq;          ber_out_header(s, BER_TAG_OCTET_STRING, 1);     /* called domain */
133            out_uint8(s, 1);
134    
135          iso_init(conn);          ber_out_header(s, BER_TAG_BOOLEAN, 1);
136          cjrq.userid = conn->mcs_userid;          out_uint8(s, 0xff);     /* upward flag */
         cjrq.chanid = chanid;  
         mcs_io_cjrq(&conn->out, &cjrq);  
         MARK_END(conn->out);  
         iso_send(conn);  
 }  
137    
138  /* Initialise MCS transport data packet */          mcs_out_domain_params(s, 34, 2, 0, 0xffff);     /* target params */
139  void mcs_init_data(HCONN conn)          mcs_out_domain_params(s, 1, 1, 1, 0x420);       /* min params */
140  {          mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff);       /* max params */
         iso_init(conn);  
         PUSH_LAYER(conn->out, mcs_offset, 8);  
 }  
141    
142  /* Transmit MCS transport data packet */          ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
143  void mcs_send_data(HCONN conn, uint16 chanid, BOOL request)          out_uint8p(s, mcs_data->data, datalen);
 {  
         MCS_DATA dt;  
144    
145          POP_LAYER(conn->out, mcs_offset);          s_mark_end(s);
146          dt.userid = conn->mcs_userid;          iso_send(s);
         dt.chanid = chanid;  
         dt.flags = 0x70;  
         dt.length = conn->out.end - conn->out.offset - 8;  
         mcs_io_data(&conn->out, &dt, request);  
         iso_send(conn);  
147  }  }
148    
149  /* Receive a message on the MCS layer */  /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
150  BOOL mcs_recv(HCONN conn, BOOL request)  static BOOL
151    mcs_recv_connect_response(STREAM mcs_data)
152  {  {
153          MCS_DATA data;          uint8 result;
154            int length;
155            STREAM s;
156    
157          if (!iso_recv(conn) || !mcs_io_data(&conn->in, &data, request))          s = iso_recv(NULL);
158            if (s == NULL)
159                  return False;                  return False;
160    
161          conn->in.rdp_offset = conn->in.offset;          ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
         return True;  
 }  
162    
163  /* Initialise a DOMAIN_PARAMS structure */          ber_parse_header(s, BER_TAG_RESULT, &length);
164  void mcs_make_domain_params(DOMAIN_PARAMS *dp, uint16 max_channels,          in_uint8(s, result);
165                uint16 max_users, uint16 max_tokens, uint16 max_pdusize)          if (result != 0)
 {  
         dp->max_channels   = max_channels;  
         dp->max_users      = max_users;  
         dp->max_tokens     = max_tokens;  
         dp->num_priorities = 1;  
         dp->min_throughput = 0;  
         dp->max_height     = 1;  
         dp->max_pdusize    = max_pdusize;  
         dp->ver_protocol   = 2;  
 }  
   
 /* RDP-specific 'user data'. Let's just get this right for now - to be  
    decoded later. */  
 char precanned_connect_userdata[] = {  
    0x00,0x05,0x00,0x14,0x7c,0x00,0x01,0x80,0x9e,0x00,0x08,0x00,0x10,0x00,  
    0x01,0xc0,0x00,0x44,0x75,0x63,0x61,0x80,0x90,0x01,0xc0,0x88,0x00,0x01,  
    0x00,0x08,0x00,0x80,0x02,0xe0,0x01,0x01,0xca,0x03,0xaa,0x09,0x04,0x00,  
    0x00,0xa3,0x01,0x00,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x31,0x00,0x2d,  
    0x00,0x4e,0x00,0x45,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
    0x00,0x01,0xca,0x00,0x00,0x02,0xc0,0x08,0x00,  
    /* encryption disabled */ 0x00,0x00,0x00,0x00 };  
   
 char precanned_connect_userdata_e[] = {  
 0x00,  
 0x05,0x00,0x14,0x7c,0x00,0x01,0x80,0x9e,0x00,0x08,0x00,0x10,0x00,0x01,0xc0,0x00,  
 0x44,0x75,0x63,0x61,0x80,0x90,0x01,0xc0,0x88,0x00,0x01,0x00,0x08,0x00,0x80,0x02,  
 0xe0,0x01,0x01,0xca,0x03,0xaa,0x09,0x04,0x00,0x00,0xa3,0x01,0x00,0x00,0x57,0x00,  
 0x49,0x00,0x4e,0x00,0x39,0x00,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xca,0x00,0x00,0x02,0xc0,  
 0x08,0x00,0x01,0x00,0x00,0x00  
 };  
   
 char domain_data[] = {0x01};  
   
 /* Initialise a MCS_CONNECT_INITIAL structure */  
 void mcs_make_connect_initial(MCS_CONNECT_INITIAL *mci)  
 {  
         mci->calling_domain.length = 1;  
         mci->calling_domain.data = domain_data;  
   
         mci->called_domain.length = 1;  
         mci->called_domain.data = domain_data;  
   
         mci->upward_flag = 0xff;  
   
         mcs_make_domain_params(&mci->target_params,  2, 2, 0, 0xffff);  
         mcs_make_domain_params(&mci->minimum_params, 1, 1, 1, 0x420);  
         mcs_make_domain_params(&mci->maximum_params, 0xffff, 0xfc17, 0xffff,  
                                0xffff);  
   
         mci->user_data.length = sizeof(precanned_connect_userdata);  
         mci->user_data.data = precanned_connect_userdata;  
   
         mci->length = 2*2 + 3 + 3*34 + 4 + mci->user_data.length;  
 }  
   
 /* Marshall/demarshall an ASN.1 BER header */  
 BOOL ber_io_header(STREAM s, BOOL islong, int tagval, int *length)  
 {  
         uint16 word_tag;  
         uint8 byte_tag;  
         uint16 word_len;  
         uint8 byte_len;  
         uint8 byte_int;  
         int tag;  
         BOOL res;  
   
         /* Read/write tag */  
         if (islong)  
         {  
                 word_tag = tagval;  
                 res = msb_io_uint16(s, &word_tag);  
                 tag = word_tag;  
         }  
         else  
166          {          {
167                  byte_tag = tagval;                  error("MCS connect: %d\n", result);
                 res = prs_io_uint8(s, &byte_tag);  
                 tag = byte_tag;  
         }  
   
         if (!res || (tag != tagval))  
         {  
                 ERROR("Invalid ASN.1 tag\n");  
168                  return False;                  return False;
169          }          }
170    
171          /* Read/write length */          ber_parse_header(s, BER_TAG_INTEGER, &length);
172          if (s->marshall)          in_uint8s(s, length);   /* connect id */
173          {          mcs_parse_domain_params(s);
                 if (*length >= 0x80)  
                 {  
                         byte_len = 0x82;  
                         word_len = (uint16)*length;  
                         res = prs_io_uint8(s, &byte_len);  
                         res = res ? msb_io_uint16(s, &word_len) : False;  
                 }  
                 else  
                 {  
                         byte_len = (uint8)*length;  
                         res = prs_io_uint8(s, &byte_len);  
                 }  
         }  
         else  
         {  
                 if (!prs_io_uint8(s, &byte_len))  
                         return False;  
174    
175                  if (byte_len & 0x80)          ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
                 {  
                         byte_len &= ~0x80;  
                         *length = 0;  
                         while (byte_len--)  
                         {  
                                 if (!prs_io_uint8(s, &byte_int))  
                                         return False;  
   
                                 *length <<= 8;  
                                 *length += byte_int;  
                         }  
                 }  
                 else *length = byte_len;  
         }  
176    
177          return res;          sec_process_mcs_data(s);
178            /*
179               if (length > mcs_data->size)
180               {
181               error("MCS data length %d, expected %d\n", length,
182               mcs_data->size);
183               length = mcs_data->size;
184               }
185    
186               in_uint8a(s, mcs_data->data, length);
187               mcs_data->p = mcs_data->data;
188               mcs_data->end = mcs_data->data + length;
189             */
190            return s_check_end(s);
191  }  }
192    
193  /* Marshall/demarshall an octet string (ASN.1 BER) */  /* Send an EDrq message (ASN.1 PER) */
194  BOOL ber_io_octet_string(STREAM s, OCTET_STRING *os)  static void
195    mcs_send_edrq(void)
196  {  {
197          if (!ber_io_header(s, False, 4, &os->length))          STREAM s;
198                  return False;  
199            s = iso_init(5);
200    
201            out_uint8(s, (MCS_EDRQ << 2));
202            out_uint16_be(s, 1);    /* height */
203            out_uint16_be(s, 1);    /* interval */
204    
205            s_mark_end(s);
206            iso_send(s);
207    }
208    
209    /* Send an AUrq message (ASN.1 PER) */
210    static void
211    mcs_send_aurq(void)
212    {
213            STREAM s;
214    
215            s = iso_init(1);
216    
217            out_uint8(s, (MCS_AURQ << 2));
218    
219          if (os->length > s->end - s->offset)          s_mark_end(s);
220            iso_send(s);
221    }
222    
223    /* Expect a AUcf message (ASN.1 PER) */
224    static BOOL
225    mcs_recv_aucf(uint16 * mcs_userid)
226    {
227            uint8 opcode, result;
228            STREAM s;
229    
230            s = iso_recv(NULL);
231            if (s == NULL)
232                  return False;                  return False;
233    
234          if (s->marshall)          in_uint8(s, opcode);
235            if ((opcode >> 2) != MCS_AUCF)
236          {          {
237                  memcpy(s->data + s->offset, os->data, os->length);                  error("expected AUcf, got %d\n", opcode);
238                    return False;
239          }          }
240          else  
241            in_uint8(s, result);
242            if (result != 0)
243          {          {
244                  os->data = malloc(os->length);                  error("AUrq: %d\n", result);
245                  memcpy(os->data, s->data + s->offset, os->length);                  return False;
246          }          }
247    
248          s->offset += os->length;          if (opcode & 2)
249          return True;                  in_uint16_be(s, *mcs_userid);
250    
251            return s_check_end(s);
252  }  }
253    
254  /* Marshall/demarshall an integer (ASN.1 BER) */  /* Send a CJrq message (ASN.1 PER) */
255  BOOL ber_io_integer(STREAM s, uint16 *word_int)  static void
256    mcs_send_cjrq(uint16 chanid)
257  {  {
258          int length = 2;          STREAM s;
         uint8 byte_int;  
         BOOL res;  
259    
260          if (!ber_io_header(s, False, 2, &length))          DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
                 return False;  
261    
262          if (s->marshall)          s = iso_init(5);
         {  
                 res = msb_io_uint16(s, word_int);  
         }  
         else  
         {  
                 *word_int = 0;  
                 while (length--)  
                 {  
                         if (!prs_io_uint8(s, &byte_int))  
                                 return False;  
263    
264                          *word_int <<= 8;          out_uint8(s, (MCS_CJRQ << 2));
265                          *word_int += byte_int;          out_uint16_be(s, g_mcs_userid);
266                  }          out_uint16_be(s, chanid);
         }  
267    
268          return res;          s_mark_end(s);
269            iso_send(s);
270  }  }
271    
272  /* Marshall/demarshall a simple uint8 type (ASN.1 BER) */  /* Expect a CJcf message (ASN.1 PER) */
273  BOOL ber_io_uint8(STREAM s, uint8 *i, int tagval)  static BOOL
274    mcs_recv_cjcf(void)
275  {  {
276          int length = 1;          uint8 opcode, result;
277            STREAM s;
278    
279          if (!ber_io_header(s, False, tagval, &length))          s = iso_recv(NULL);
280            if (s == NULL)
281                  return False;                  return False;
282    
283          if (length != 1)          in_uint8(s, opcode);
284            if ((opcode >> 2) != MCS_CJCF)
285            {
286                    error("expected CJcf, got %d\n", opcode);
287                    return False;
288            }
289    
290            in_uint8(s, result);
291            if (result != 0)
292          {          {
293                  ERROR("Wrong length for simple type\n");                  error("CJrq: %d\n", result);
294                  return False;                  return False;
295          }          }
296    
297          return prs_io_uint8(s, i);          in_uint8s(s, 4);        /* mcs_userid, req_chanid */
298            if (opcode & 2)
299                    in_uint8s(s, 2);        /* join_chanid */
300    
301            return s_check_end(s);
302  }  }
303    
304  /* Marshall/demarshall a DOMAIN_PARAMS structure (ASN.1 BER) */  /* Initialise an MCS transport data packet */
305  BOOL mcs_io_domain_params(STREAM s, DOMAIN_PARAMS *dp)  STREAM
306    mcs_init(int length)
307  {  {
308          int length = 32;          STREAM s;
         BOOL res;  
309    
310          res = ber_io_header(s, False, 0x30, &length);          s = iso_init(length + 8);
311          res = res ? ber_io_integer(s, &dp->max_channels  ) : False;          s_push_layer(s, mcs_hdr, 8);
         res = res ? ber_io_integer(s, &dp->max_users     ) : False;  
         res = res ? ber_io_integer(s, &dp->max_tokens    ) : False;  
         res = res ? ber_io_integer(s, &dp->num_priorities) : False;  
         res = res ? ber_io_integer(s, &dp->min_throughput) : False;  
         res = res ? ber_io_integer(s, &dp->max_height    ) : False;  
         res = res ? ber_io_integer(s, &dp->max_pdusize   ) : False;  
         res = res ? ber_io_integer(s, &dp->ver_protocol  ) : False;  
312    
313          return res;          return s;
314  }  }
315    
316  /* Marshall/demarshall a MCS_CONNECT_INITIAL structure (ASN.1 BER) */  /* Send an MCS transport data packet to a specific channel */
317  BOOL mcs_io_connect_initial(STREAM s, MCS_CONNECT_INITIAL *mci)  void
318    mcs_send_to_channel(STREAM s, uint16 channel)
319  {  {
320          BOOL res;          uint16 length;
321    
322            s_pop_layer(s, mcs_hdr);
323            length = s->end - s->p - 8;
324            length |= 0x8000;
325    
326          res = ber_io_header(s, True, 0x7f65, &mci->length);          out_uint8(s, (MCS_SDRQ << 2));
327          res = res ? ber_io_octet_string (s, &mci->calling_domain) : False;          out_uint16_be(s, g_mcs_userid);
328          res = res ? ber_io_octet_string (s, &mci->called_domain ) : False;          out_uint16_be(s, channel);
329          res = res ? ber_io_uint8        (s, &mci->upward_flag, 1) : False;          out_uint8(s, 0x70);     /* flags */
330          res = res ? mcs_io_domain_params(s, &mci->target_params ) : False;          out_uint16_be(s, length);
         res = res ? mcs_io_domain_params(s, &mci->minimum_params) : False;  
         res = res ? mcs_io_domain_params(s, &mci->maximum_params) : False;  
         res = res ? ber_io_octet_string (s, &mci->user_data     ) : False;  
331    
332          return res;          iso_send(s);
333  }  }
334    
335  /* Marshall/demarshall a MCS_CONNECT_RESPONSE structure (ASN.1 BER) */  /* Send an MCS transport data packet to the global channel */
336  BOOL mcs_io_connect_response(STREAM s, MCS_CONNECT_RESPONSE *mcr)  void
337    mcs_send(STREAM s)
338  {  {
339          BOOL res;          mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
   
         res = ber_io_header(s, True, 0x7f66, &mcr->length);  
         res = res ? ber_io_uint8        (s, &mcr->result, 10   ) : False;  
         res = res ? ber_io_integer      (s, &mcr->connect_id   ) : False;  
         res = res ? mcs_io_domain_params(s, &mcr->domain_params) : False;  
         res = res ? ber_io_octet_string (s, &mcr->user_data    ) : False;  
   
         return res;  
340  }  }
341    
342  /* Marshall/demarshall an EDrq structure (ASN.1 PER) */  /* Receive an MCS transport data packet */
343  BOOL mcs_io_edrq(STREAM s, MCS_EDRQ *edrq)  STREAM
344    mcs_recv(uint16 * channel, uint8 * rdpver)
345  {  {
346          uint8 opcode = (1) << 2;          uint8 opcode, appid, length;
347          uint8 pkt_opcode = opcode;          STREAM s;
         BOOL res;  
348    
349          res = prs_io_uint8(s, &pkt_opcode);          s = iso_recv(rdpver);
350          if (pkt_opcode != opcode)          if (s == NULL)
351                    return NULL;
352            if (rdpver != NULL)
353                    if (*rdpver != 3)
354                            return s;
355            in_uint8(s, opcode);
356            appid = opcode >> 2;
357            if (appid != MCS_SDIN)
358          {          {
359                  ERROR("Expected EDrq, received %x\n", pkt_opcode);                  if (appid != MCS_DPUM)
360                  return False;                  {
361                            error("expected data, got %d\n", opcode);
362                    }
363                    return NULL;
364          }          }
365            in_uint8s(s, 2);        /* userid */
366          res = res ? msb_io_uint16(s, &edrq->height  ) : False;          in_uint16_be(s, *channel);
367          res = res ? msb_io_uint16(s, &edrq->interval) : False;          in_uint8s(s, 1);        /* flags */
368            in_uint8(s, length);
369          return res;          if (length & 0x80)
370                    in_uint8s(s, 1);        /* second byte of length */
371            return s;
372  }  }
373    
374  /* Marshall/demarshall an AUrq structure (ASN.1 PER) */  /* Establish a connection up to the MCS layer */
375  BOOL mcs_io_aurq(STREAM s, MCS_AURQ *aurq)  BOOL
376    mcs_connect(char *server, STREAM mcs_data, char *username)
377  {  {
378          uint8 opcode = (10) << 2;          unsigned int i;
         uint8 pkt_opcode = opcode;  
         BOOL res;  
379    
380          res = prs_io_uint8(s, &pkt_opcode);          if (!iso_connect(server, username))
         if (pkt_opcode != opcode)  
         {  
                 ERROR("Expected AUrq, received %x\n", pkt_opcode);  
381                  return False;                  return False;
         }  
382    
383          return res;          mcs_send_connect_initial(mcs_data);
384  }          if (!mcs_recv_connect_response(mcs_data))
385                    goto error;
386    
387  /* Marshall/demarshall an AUcf structure (ASN.1 PER) */          mcs_send_edrq();
 BOOL mcs_io_aucf(STREAM s, MCS_AUCF *aucf)  
 {  
         uint8 opcode = (11) << 2;  
         uint8 pkt_opcode = opcode | 2;  
         BOOL res;  
388    
389          res = prs_io_uint8(s, &pkt_opcode);          mcs_send_aurq();
390          if ((pkt_opcode & 0xfc) != opcode)          if (!mcs_recv_aucf(&g_mcs_userid))
391          {                  goto error;
                 ERROR("Expected AUcf, received %x\n", pkt_opcode);  
                 return False;  
         }  
392    
393          res = res ? prs_io_uint8 (s, &aucf->result) : False;          mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
         if (pkt_opcode & 2)  
                 res = res ? msb_io_uint16(s, &aucf->userid) : False;  
394    
395          return res;          if (!mcs_recv_cjcf())
396  }                  goto error;
397    
398  /* Marshall/demarshall an CJrq structure (ASN.1 PER) */          mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
399  BOOL mcs_io_cjrq(STREAM s, MCS_CJRQ *cjrq)          if (!mcs_recv_cjcf())
400  {                  goto error;
         uint8 opcode = (14) << 2;  
         uint8 pkt_opcode = opcode;  
         BOOL res;  
401    
402          res = prs_io_uint8(s, &pkt_opcode);          for (i = 0; i < g_num_channels; i++)
         if (pkt_opcode != opcode)  
403          {          {
404                  ERROR("Expected CJrq, received %x\n", pkt_opcode);                  mcs_send_cjrq(g_channels[i].mcs_id);
405                  return False;                  if (!mcs_recv_cjcf())
406                            goto error;
407          }          }
408            return True;
409    
410          res = res ? msb_io_uint16(s, &cjrq->userid) : False;        error:
411          res = res ? msb_io_uint16(s, &cjrq->chanid) : False;          iso_disconnect();
412            return False;
         return res;  
413  }  }
414    
415  /* Marshall/demarshall an CJcf structure (ASN.1 PER) */  /* Establish a connection up to the MCS layer */
416  BOOL mcs_io_cjcf(STREAM s, MCS_CJCF *cjcf)  BOOL
417    mcs_reconnect(char *server, STREAM mcs_data)
418  {  {
419          uint8 opcode = (15) << 2;          unsigned int i;
         uint8 pkt_opcode = opcode | 2;  
         BOOL res;  
420    
421          res = prs_io_uint8(s, &pkt_opcode);          if (!iso_reconnect(server))
         if ((pkt_opcode & 0xfc) != opcode)  
         {  
                 ERROR("Expected CJcf, received %x\n", pkt_opcode);  
422                  return False;                  return False;
         }  
423    
424          res = res ? prs_io_uint8 (s, &cjcf->result) : False;          mcs_send_connect_initial(mcs_data);
425          res = res ? msb_io_uint16(s, &cjcf->userid) : False;          if (!mcs_recv_connect_response(mcs_data))
426          res = res ? msb_io_uint16(s, &cjcf->req_chanid) : False;                  goto error;
         if (pkt_opcode & 2)  
                 res = res ? msb_io_uint16(s, &cjcf->join_chanid) : False;  
427    
428          return res;          mcs_send_edrq();
 }  
429    
430  /* Marshall/demarshall an SDrq or SDin packet (ASN.1 PER) */          mcs_send_aurq();
431  BOOL mcs_io_data(STREAM s, MCS_DATA *dt, BOOL request)          if (!mcs_recv_aucf(&g_mcs_userid))
432  {                  goto error;
         uint8 opcode = (request ? 25 : 26) << 2;  
         uint8 pkt_opcode = opcode;  
         uint8 byte1, byte2;  
         BOOL res;  
433    
434          res = prs_io_uint8(s, &pkt_opcode);          mcs_send_cjrq(g_mcs_userid + MCS_USERCHANNEL_BASE);
         if (pkt_opcode != opcode)  
         {  
                 ERROR("Expected MCS data, received %x\n", pkt_opcode);  
                 return False;  
         }  
435    
436          res = res ? msb_io_uint16(s, &dt->userid) : False;          if (!mcs_recv_cjcf())
437          res = res ? msb_io_uint16(s, &dt->chanid) : False;                  goto error;
         res = res ? prs_io_uint8 (s, &dt->flags ) : False;  
438    
439          if (s->marshall)          mcs_send_cjrq(MCS_GLOBAL_CHANNEL);
440          {          if (!mcs_recv_cjcf())
441                  dt->length |= 0x8000;                  goto error;
442                  res = res ? msb_io_uint16(s, &dt->length) : False;  
443          }          for (i = 0; i < g_num_channels; i++)
         else  
444          {          {
445                  res = res ? prs_io_uint8(s, &byte1) : False;                  mcs_send_cjrq(g_channels[i].mcs_id);
446                  if (byte1 & 0x80)                  if (!mcs_recv_cjcf())
447                  {                          goto error;
                         res = res ? prs_io_uint8(s, &byte2) : False;  
                         dt->length = ((byte1 & ~0x80) << 8) + byte2;  
                 }  
                 else dt->length = byte1;  
448          }          }
449            return True;
450    
451          error:
452            iso_disconnect();
453            return False;
454    }
455    
456          return res;  /* Disconnect from the MCS layer */
457    void
458    mcs_disconnect(void)
459    {
460            iso_disconnect();
461  }  }
462    
463    /* reset the state of the mcs layer */
464    void
465    mcs_reset_state(void)
466    {
467            g_mcs_userid = 0;
468            iso_reset_state();
469    }

Legend:
Removed from v.9  
changed lines
  Added in v.1365

  ViewVC Help
Powered by ViewVC 1.1.26