]> git.sesse.net Git - rdpsrv/blob - mcs.c
6e13770f5f74adc9145bedca2445519258a26527
[rdpsrv] / mcs.c
1 /* -*- c-basic-offset: 8 -*-
2    rdesktop: A Remote Desktop Protocol client.
3    Protocol services - Multipoint Communications Service
4    Copyright (C) Matthew Chapman 1999-2002
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
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "rdesktop.h"
22 #include <openssl/rsa.h>
23
24 uint16 g_mcs_userid;
25 extern VCHANNEL g_channels[];
26 extern unsigned int g_num_channels;
27 extern RSA *privkey;
28
29 /* Parse an ASN.1 BER header */
30 static BOOL
31 ber_parse_header(STREAM s, int tagval, int *length)
32 {
33         int tag, len;
34
35         if (tagval > 0xff)
36         {
37                 in_uint16_be(s, tag);
38         }
39         else
40         {
41         in_uint8(s, tag)}
42
43         if (tag != tagval)
44         {
45                 error("expected tag %d, got %d\n", tagval, tag);
46                 return False;
47         }
48
49         in_uint8(s, len);
50
51         if (len & 0x80)
52         {
53                 len &= ~0x80;
54                 *length = 0;
55                 while (len--)
56                         next_be(s, *length);
57         }
58         else
59                 *length = len;
60
61         return s_check(s);
62 }
63
64 /* Output an ASN.1 BER header */
65 static void
66 ber_out_header(STREAM s, int tagval, int length)
67 {
68         if (tagval > 0xff)
69         {
70                 out_uint16_be(s, tagval);
71         }
72         else
73         {
74                 out_uint8(s, tagval);
75         }
76
77         if (length >= 0x80)
78         {
79                 out_uint8(s, 0x82);
80                 out_uint16_be(s, length);
81         }
82         else
83                 out_uint8(s, length);
84 }
85
86 /* Output an ASN.1 BER integer */
87 static void
88 ber_out_integer(STREAM s, int value)
89 {
90         ber_out_header(s, BER_TAG_INTEGER, 2);
91         out_uint16_be(s, value);
92 }
93
94 static void
95 ber_out_uint8(STREAM s, uint8 value)
96 {
97         ber_out_header(s, BER_TAG_INTEGER, 1);
98         out_uint8(s, value);
99 }
100
101 static void
102 ber_in_integer(STREAM s, int *value)
103 {
104         int length;
105         ber_parse_header(s, BER_TAG_INTEGER, &length);
106         in_uint16_be(s, *value);
107 }
108
109 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
110 static void
111 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
112 {
113         ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 26);
114         ber_out_uint8(s, 34); // max_channels
115         ber_out_uint8(s, 3);  // max_users
116         ber_out_uint8(s, 0);  // max_tokens
117         ber_out_uint8(s, 1);  // num_priorities 
118         ber_out_uint8(s, 0);  // min_throughput
119         ber_out_uint8(s, 1);  // max_height
120         ber_out_header(s, BER_TAG_INTEGER, 3); // pdu size
121         out_uint8(s, 0x00);
122         out_uint8(s, 0xff);
123         out_uint8(s, 0xf8);
124         ber_out_uint8(s, 2);  // ver_protocol
125 }
126
127 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
128 static BOOL
129 mcs_parse_domain_params(STREAM s)
130 {
131         int length;
132         int max_channels, max_users, max_tokens, max_pdusize;
133         int num_priorities, min_throughput, max_height;
134         int ver_protocol;
135
136         ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
137         printf("MCS_TAG_DOMAIN_PARAMS, len %u (expected 32)\n", length);
138         if (length == 32) {
139                 ber_in_integer(s, &max_channels);
140                 ber_in_integer(s, &max_users);
141                 ber_in_integer(s, &max_tokens);
142                 ber_in_integer(s, &num_priorities);
143                 ber_in_integer(s, &min_throughput);
144                 ber_in_integer(s, &max_height);
145                 ber_in_integer(s, &max_pdusize);
146                 ber_in_integer(s, &ver_protocol);
147
148                 printf("max_channels=%u\n", max_channels);
149                 printf("max_users=%u\n", max_users);
150                 printf("max_tokens=%u\n", max_tokens);
151                 printf("num_priorities=%u\n", num_priorities);
152                 printf("min_throughput=%u\n", min_throughput);
153                 printf("max_pdusize=%u\n", max_pdusize);
154                 printf("ver_protocol=%u\n", ver_protocol);
155         } else {
156                 hexdump(s->p, length);
157                 in_uint8s(s, length);
158         }
159         
160         return s_check(s);
161 }
162
163 /* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
164 BOOL
165 mcs_recv_connect_initial()
166 {
167         uint8 result;
168         int length;
169         STREAM s;
170         char *buf;
171
172         s = iso_recv();
173         if (s == NULL)
174                 return False;
175
176         ber_parse_header(s, MCS_CONNECT_INITIAL, &length);
177         printf("parsing MCS_CONNECT_INITIAL (len=%u)\n", length);
178         ber_parse_header(s, BER_TAG_OCTET_STRING, &length);   /* calling domain */
179         in_uint8(s, result);
180         ber_parse_header(s, BER_TAG_OCTET_STRING, &length);   /* called domain */
181         in_uint8(s, result);
182         
183         ber_parse_header(s, BER_TAG_BOOLEAN, &length);
184         in_uint8(s, result);
185
186         mcs_parse_domain_params(s);
187         mcs_parse_domain_params(s);
188         mcs_parse_domain_params(s);
189
190         ber_parse_header(s, BER_TAG_OCTET_STRING, &length);
191         in_uint8p(s, buf, length);
192
193         printf("Data from MCS connect: '%*s'\n", length, buf);
194         
195         return s_check_end(s);
196 }
197
198 /* keys grabbed from rdpproxy, look at http://www.cse.unsw.edu.au/~matthewc/rdesktop/rdpproxy/openssl/ */
199 unsigned char cacert[] = {
200         0x30, 0x82, 0x01, 0x6b, 0x30, 0x82, 0x01, 0x19, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x01,
201         0x9d, 0xfb, 0xeb, 0x46, 0x78, 0x5b, 0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
202         0x05, 0x00, 0x30, 0x34, 0x31, 0x32, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0e, 0x00,
203         0x56, 0x00, 0x49, 0x00, 0x56, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x49, 0x30, 0x19, 0x06,
204         0x03, 0x55, 0x04, 0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47,
205         0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x32, 0x30, 0x36,
206         0x33, 0x30, 0x31, 0x35, 0x31, 0x31, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x30, 0x33, 0x30, 0x36, 0x33,
207         0x30, 0x31, 0x35, 0x31, 0x31, 0x31, 0x39, 0x5a, 0x30, 0x34, 0x31, 0x32, 0x30, 0x15, 0x06, 0x03,
208         0x55, 0x04, 0x03, 0x1e, 0x0e, 0x00, 0x56, 0x00, 0x49, 0x00, 0x56, 0x00, 0x41, 0x00, 0x4c, 0x00,
209         0x44, 0x00, 0x49, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f,
210         0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x5c,
211         0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
212         0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xc8, 0xc6, 0xb4, 0xd6, 0x31, 0x35, 0x5e, 0x6f, 0x01,
213         0x06, 0x1a, 0x02, 0x1d, 0x55, 0x46, 0x91, 0xe6, 0xa0, 0x19, 0x28, 0x4d, 0x87, 0x28, 0x5d, 0x22,
214         0xc8, 0xba, 0x8b, 0x6b, 0x93, 0x18, 0xbb, 0x93, 0x47, 0x14, 0xe5, 0x85, 0xe4, 0xfc, 0x49, 0x3d,
215         0x94, 0xbd, 0x5b, 0x2f, 0x7d, 0x0e, 0xa4, 0xa8, 0xc2, 0x79, 0x7c, 0x74, 0x6e, 0x39, 0x5d, 0x8a,
216         0xe4, 0x71, 0x22, 0xca, 0x37, 0x7e, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x13, 0x30, 0x11,
217         0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01,
218         0x00, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x12,
219         0x79, 0xdd, 0xf9, 0x90, 0xb0, 0x39, 0x24, 0x35, 0x4d, 0x0b, 0xc6, 0xff, 0x8a, 0x96, 0x10, 0x4b,
220         0xac, 0xd0, 0x26, 0x5e, 0x44, 0xe1, 0x09, 0x72, 0x1b, 0xad, 0x4e, 0x34, 0x78, 0x32, 0xde, 0x29,
221         0x11, 0x08, 0x31, 0xba, 0x6d, 0x1b, 0x42, 0x7a, 0xa7, 0x45, 0xc6, 0xb7, 0xd3, 0xd3, 0x0f, 0x8b,
222         0xf3, 0xe5, 0x57, 0xde, 0x0d, 0x0c, 0xc1, 0x75, 0x60, 0x57, 0x1c, 0x0e, 0xf8, 0xf3, 0x0c
223 };
224 unsigned char server_cert[] = {
225         0x30, 0x82, 0x03, 0x79, 0x30, 0x82, 0x03, 0x27, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x05, 0x01,
226         0x00, 0x00, 0x00, 0x03, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30,
227         0x34, 0x31, 0x32, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0e, 0x00, 0x56, 0x00, 0x49,
228         0x00, 0x56, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x49, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
229         0x07, 0x1e, 0x12, 0x00, 0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00,
230         0x4f, 0x00, 0x55, 0x00, 0x50, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x32, 0x30, 0x36, 0x33, 0x30, 0x31,
231         0x35, 0x31, 0x32, 0x30, 0x38, 0x5a, 0x17, 0x0d, 0x30, 0x33, 0x30, 0x36, 0x33, 0x30, 0x31, 0x35,
232         0x31, 0x32, 0x30, 0x38, 0x5a, 0x30, 0x81, 0x92, 0x31, 0x81, 0x8f, 0x30, 0x25, 0x06, 0x03, 0x55,
233         0x04, 0x03, 0x1e, 0x1e, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x70,
234         0x00, 0x63, 0x00, 0x3a, 0x00, 0x56, 0x00, 0x49, 0x00, 0x56, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x44,
235         0x00, 0x49, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x07, 0x1e, 0x1e, 0x00, 0x6e, 0x00, 0x63, 0x00,
236         0x61, 0x00, 0x6c, 0x00, 0x72, 0x00, 0x70, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x56, 0x00, 0x49, 0x00,
237         0x56, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x49, 0x30, 0x3f, 0x06, 0x03, 0x55, 0x04, 0x05,
238         0x1e, 0x38, 0x00, 0x31, 0x00, 0x42, 0x00, 0x63, 0x00, 0x4b, 0x00, 0x65, 0x00, 0x57, 0x00, 0x39,
239         0x00, 0x64, 0x00, 0x34, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x59, 0x00, 0x44, 0x00, 0x48, 0x00, 0x2f,
240         0x00, 0x56, 0x00, 0x35, 0x00, 0x65, 0x00, 0x67, 0x00, 0x45, 0x00, 0x72, 0x00, 0x70, 0x00, 0x66,
241         0x00, 0x55, 0x00, 0x55, 0x00, 0x4f, 0x00, 0x63, 0x00, 0x3d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09,
242         0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48,
243         0x02, 0x41, 0x00, 0xb6, 0x88, 0xff, 0x4a, 0x6d, 0x44, 0x59, 0x6c, 0x3a, 0xe8, 0x5b, 0x53, 0x72,
244         0x2e, 0x0a, 0x3f, 0x0b, 0xbf, 0x33, 0x87, 0x25, 0x30, 0xeb, 0x82, 0xf7, 0xd4, 0x98, 0xf1, 0x60,
245         0xee, 0x6e, 0x99, 0xdd, 0x6f, 0x07, 0xd9, 0xc0, 0xa1, 0x6c, 0x1c, 0x50, 0xd7, 0xc1, 0x18, 0xe1,
246         0x5e, 0x70, 0x89, 0x3e, 0x6a, 0x98, 0x2c, 0x8b, 0xef, 0x76, 0x6d, 0x9b, 0x70, 0xb8, 0xd7, 0x41,
247         0x25, 0xa1, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xc3, 0x30, 0x82, 0x01, 0xbf,
248         0x30, 0x14, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12, 0x04, 0x01, 0x01, 0xff,
249         0x04, 0x04, 0x01, 0x00, 0x05, 0x00, 0x30, 0x3c, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
250         0x37, 0x12, 0x02, 0x01, 0x01, 0xff, 0x04, 0x2c, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00,
251         0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00,
252         0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00,
253         0x6e, 0x00, 0x00, 0x00, 0x30, 0x81, 0xcd, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
254         0x12, 0x05, 0x01, 0x01, 0xff, 0x04, 0x81, 0xbc, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
255         0x02, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x1c, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x4a, 0x00,
256         0xb0, 0x00, 0x01, 0x00, 0x33, 0x00, 0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, 0x00,
257         0x35, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00,
258         0x31, 0x00, 0x31, 0x00, 0x64, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00,
259         0x65, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00,
260         0x61, 0x00, 0x33, 0x00, 0x30, 0x00, 0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x33, 0x00,
261         0x64, 0x00, 0x32, 0x00, 0x36, 0x00, 0x37, 0x00, 0x39, 0x00, 0x35, 0x00, 0x34, 0x00, 0x2d, 0x00,
262         0x65, 0x00, 0x65, 0x00, 0x62, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x31, 0x00, 0x64, 0x00,
263         0x31, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x39, 0x00, 0x34, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x30, 0x00,
264         0x30, 0x00, 0x63, 0x00, 0x30, 0x00, 0x34, 0x00, 0x66, 0x00, 0x61, 0x00, 0x33, 0x00, 0x30, 0x00,
265         0x38, 0x00, 0x30, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0xd4, 0x00,
266         0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x12,
267         0x06, 0x01, 0x01, 0xff, 0x04, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00,
268         0x56, 0x00, 0x49, 0x00, 0x56, 0x00, 0x41, 0x00, 0x4c, 0x00, 0x44, 0x00, 0x49, 0x00, 0x00, 0x00,
269         0x35, 0x00, 0x31, 0x00, 0x38, 0x00, 0x37, 0x00, 0x39, 0x00, 0x2d, 0x00, 0x33, 0x00, 0x33, 0x00,
270         0x35, 0x00, 0x2d, 0x00, 0x38, 0x00, 0x33, 0x00, 0x39, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00,
271         0x37, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x39, 0x00, 0x33, 0x00, 0x37, 0x00, 0x38, 0x00, 0x00, 0x00,
272         0x57, 0x00, 0x4f, 0x00, 0x52, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x52, 0x00, 0x4f, 0x00, 0x55, 0x00,
273         0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x27, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x01, 0x01, 0xff,
274         0x04, 0x1d, 0x30, 0x1b, 0xa1, 0x12, 0xa4, 0x10, 0x56, 0x00, 0x49, 0x00, 0x56, 0x00, 0x41, 0x00,
275         0x4c, 0x00, 0x44, 0x00, 0x49, 0x00, 0x00, 0x00, 0x82, 0x05, 0x01, 0x00, 0x00, 0x00, 0x03, 0x30,
276         0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0xa8, 0x61, 0x11,
277         0x69, 0xab, 0x41, 0xee, 0x71, 0xd0, 0xa8, 0x4c, 0x8f, 0x65, 0x9d, 0x9d, 0xaf, 0xab, 0x4f, 0x43,
278         0xaf, 0xa8, 0x21, 0xb7, 0xf2, 0x2c, 0x3a, 0xa5, 0xfe, 0x9e, 0x2c, 0xbc, 0xbb, 0x5c, 0x64, 0x31,
279         0x15, 0x3c, 0xdc, 0x09, 0x4c, 0x36, 0x9a, 0x2b, 0x5e, 0xe0, 0xe6, 0x07, 0x79, 0xfd, 0xcd, 0x1d,
280         0x06, 0x63, 0xfa, 0xb4, 0x2c, 0xcc, 0x00, 0x25, 0x43, 0x71, 0x65, 0xff, 0xf7
281 };
282 unsigned char private_key[] = {
283         0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xb6, 0x88, 0xff, 0x4a, 0x6d, 0x44,
284         0x59, 0x6c, 0x3a, 0xe8, 0x5b, 0x53, 0x72, 0x2e, 0x0a, 0x3f, 0x0b, 0xbf, 0x33, 0x87, 0x25, 0x30,
285         0xeb, 0x82, 0xf7, 0xd4, 0x98, 0xf1, 0x60, 0xee, 0x6e, 0x99, 0xdd, 0x6f, 0x07, 0xd9, 0xc0, 0xa1,
286         0x6c, 0x1c, 0x50, 0xd7, 0xc1, 0x18, 0xe1, 0x5e, 0x70, 0x89, 0x3e, 0x6a, 0x98, 0x2c, 0x8b, 0xef,
287         0x76, 0x6d, 0x9b, 0x70, 0xb8, 0xd7, 0x41, 0x25, 0xa1, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
288         0x40, 0x1f, 0xf8, 0x02, 0x6e, 0x30, 0x90, 0xe5, 0xf0, 0x74, 0xa8, 0xb9, 0x45, 0xf6, 0x1b, 0x66,
289         0x24, 0x00, 0x94, 0xae, 0x1b, 0x9f, 0x41, 0xe0, 0x1d, 0x81, 0xf6, 0x34, 0x0b, 0x22, 0x64, 0xdf,
290         0xed, 0xbb, 0x05, 0xfb, 0x56, 0xcb, 0xb7, 0xef, 0x14, 0xf6, 0xb7, 0x62, 0xb5, 0x5c, 0xaf, 0x98,
291         0xf8, 0x90, 0x4d, 0x40, 0x4b, 0xc4, 0xf2, 0x1c, 0x79, 0xe5, 0x81, 0x4c, 0xae, 0xa9, 0x60, 0xf3,
292         0x21, 0x02, 0x21, 0x00, 0xdb, 0x74, 0x23, 0x81, 0x46, 0xa4, 0x28, 0x97, 0xc1, 0x88, 0x3f, 0x07,
293         0xbd, 0xdc, 0x39, 0xa7, 0x16, 0xff, 0x75, 0xaa, 0x5e, 0x61, 0xff, 0xe4, 0x5c, 0x0e, 0x3d, 0xbd,
294         0x05, 0x90, 0xc8, 0xbd, 0x02, 0x21, 0x00, 0xd4, 0xee, 0xed, 0xdf, 0xca, 0x71, 0xb7, 0x07, 0xb5,
295         0x87, 0xf2, 0xe7, 0xfa, 0xd9, 0xa6, 0xe3, 0x5f, 0xe5, 0x2a, 0x9a, 0xaf, 0x23, 0x88, 0xbc, 0x52,
296         0xb7, 0xad, 0x1b, 0x9d, 0x3c, 0x27, 0x95, 0x02, 0x20, 0x74, 0x47, 0x3c, 0x4c, 0xd2, 0x46, 0x46,
297         0xef, 0xe9, 0xee, 0xac, 0x1f, 0x08, 0xfd, 0x78, 0x5a, 0xcd, 0x77, 0xbc, 0x3b, 0xf2, 0x58, 0x90,
298         0xc2, 0xc9, 0xf8, 0x0d, 0xc4, 0x6a, 0xff, 0x85, 0x2d, 0x02, 0x21, 0x00, 0xa2, 0x4e, 0x79, 0x8d,
299         0x83, 0x3f, 0xc8, 0xb7, 0x1c, 0x9d, 0x42, 0xff, 0xa6, 0xcb, 0x6f, 0x15, 0x94, 0x0c, 0x17, 0xbc,
300         0x8e, 0xd1, 0x74, 0x31, 0xb0, 0x8f, 0x87, 0x69, 0x2c, 0x22, 0x25, 0x3d, 0x02, 0x20, 0x24, 0x9e,
301         0xf6, 0x03, 0x5f, 0x7e, 0x2d, 0xc7, 0x8c, 0x88, 0xf7, 0x43, 0x14, 0xb7, 0x75, 0x72, 0x1e, 0x16,
302         0xae, 0x43, 0x71, 0x97, 0xcc, 0xc2, 0x0c, 0xde, 0x63, 0x35, 0x87, 0x50, 0xbf, 0xad
303 };
304
305 void
306 mcs_send_connect_response()
307 {
308         STREAM s;
309         int i, length;
310
311         s = iso_init(174 + sizeof(cacert) + sizeof(server_cert));
312         printf("INITLEN: %u\n", s->p - s->iso_hdr);
313
314         ber_out_header(s, MCS_CONNECT_RESPONSE, 169 + sizeof(cacert) + sizeof(server_cert) );
315         ber_out_header(s, BER_TAG_RESULT, 1);
316         out_uint8(s, 0);
317
318         ber_out_header(s, BER_TAG_INTEGER, 1);
319         out_uint8(s, 0);  // connect id
320         
321         mcs_out_domain_params(s, 34, 2, 0, 0xffff);  // dumdidum?
322
323         ber_out_header(s, BER_TAG_OCTET_STRING, 131 + sizeof(cacert) + sizeof(server_cert));
324
325         // some unknown header of sorts
326         out_uint8(s, 0x00);
327         out_uint8(s, 0x05);
328         out_uint8(s, 0x00);
329         out_uint8(s, 0x14);
330         out_uint8(s, 0x7c);
331         out_uint8(s, 0x00);
332         out_uint8(s, 0x01);
333         out_uint8(s, 0x2a);
334         out_uint8(s, 0x14);
335         out_uint8(s, 0x76);
336         out_uint8(s, 0x0a); 
337         out_uint8(s, 0x01);
338         out_uint8(s, 0x01);
339         out_uint8(s, 0x00);
340         out_uint8(s, 0x01);
341         out_uint8(s, 0xc0);
342         out_uint8(s, 0x00);
343         out_uint8(s, 0x4d);
344         out_uint8(s, 0x63);
345         out_uint8(s, 0x44);
346         out_uint8(s, 0x6e);
347
348         length = 108 + sizeof(cacert) + sizeof(server_cert);
349         
350         // two bytes of length
351         out_uint8(s, 0x80 | (length >> 8));
352         out_uint8(s, length & 0xff);
353
354         // server info -- we claim to support RDP5
355         out_uint16_le(s, SEC_TAG_SRV_INFO);
356         out_uint16_le(s, 8);  // length
357         out_uint16_le(s, 4);  // version
358         out_uint16_le(s, 8);  // unknown
359
360         // channel info -- open a few channels
361         out_uint16_le(s, SEC_TAG_SRV_CHANNELS);
362         out_uint16_le(s, 16); // length
363         out_uint16_le(s, 1003);
364         out_uint16_le(s, 3);
365         out_uint16_le(s, 1004);
366         out_uint16_le(s, 1005);
367         out_uint16_le(s, 1006);
368         out_uint16_le(s, 0);
369         
370         // crypto info
371         out_uint16_le(s, SEC_TAG_SRV_CRYPT);
372         out_uint16_le(s, 84 + sizeof(cacert) + sizeof(server_cert)); // length
373         out_uint32_le(s, 8); // 128-bit
374         out_uint32_le(s, 2); // medium
375
376         out_uint32_le(s, SEC_RANDOM_SIZE); // random_len
377         out_uint32_le(s, 32 + sizeof(cacert) + sizeof(server_cert));             // rsa_info_len
378         out_uint8p(s, cacert, SEC_RANDOM_SIZE);    // server_"random"
379         out_uint32_le(s, 0x80000002);      // X.509
380         out_uint32_le(s, 2);               // number of certificates
381
382         // CA certificate
383         out_uint32_le(s, sizeof(cacert));
384         out_uint8p(s, cacert, sizeof(cacert));
385
386         // server certificate
387         out_uint32_le(s, sizeof(server_cert));
388         out_uint8p(s, server_cert, sizeof(server_cert));
389         
390         out_uint8s(s, 16);                 // padding
391         
392         s_mark_end(s);
393         iso_send(s);
394
395         // this is a good time to load our private key :-)
396         {
397                 unsigned char *buf = (unsigned char *)malloc(1024);
398                 unsigned char *ptr = buf;
399                 memcpy(buf, private_key, sizeof(private_key));
400                 privkey = d2i_RSAPrivateKey(NULL, &ptr, sizeof(private_key));
401                 free(buf);
402         }
403 }
404
405 /* Send an EDrq message (ASN.1 PER) */
406 static void
407 mcs_send_edrq(void)
408 {
409         STREAM s;
410
411         s = iso_init(5);
412
413         out_uint8(s, (MCS_EDRQ << 2));
414         out_uint16_be(s, 1);    /* height */
415         out_uint16_be(s, 1);    /* interval */
416
417         s_mark_end(s);
418         iso_send(s);
419 }
420
421 /* Send an AUrq message (ASN.1 PER) */
422 static void
423 mcs_send_aurq(void)
424 {
425         STREAM s;
426
427         s = iso_init(1);
428
429         out_uint8(s, (MCS_AURQ << 2));
430
431         s_mark_end(s);
432         iso_send(s);
433 }
434
435 /* Send a AUcf message (ASN.1 PER) */
436 static void
437 mcs_send_aucf(uint16 mcs_userid)
438 {
439         STREAM s;
440
441         s = iso_init(4);
442
443         out_uint8(s, (MCS_AUCF << 2) | 2);  // | 2 = send user ID
444         out_uint8(s, 0);  // success
445         out_uint16_be(s, 6);
446         
447         s_mark_end(s);
448         iso_send(s);
449 }
450
451 /* Send a CJrq message (ASN.1 PER) */
452 static void
453 mcs_send_cjrq(uint16 chanid)
454 {
455         STREAM s;
456
457         DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
458
459         s = iso_init(5);
460
461         out_uint8(s, (MCS_CJRQ << 2));
462         out_uint16_be(s, g_mcs_userid);
463         out_uint16_be(s, chanid);
464
465         s_mark_end(s);
466         iso_send(s);
467 }
468
469 /* Expect a CJcf message (ASN.1 PER) */
470 static void
471 mcs_send_cjcf(uint16 userid, uint16 chanid)
472 {
473         STREAM s;
474
475         s = iso_init(8);
476
477         out_uint8(s, (MCS_CJCF << 2) | 2);
478         out_uint8(s, 0); // success
479         out_uint16_be(s, 6);
480         out_uint16_be(s, chanid);
481         out_uint16_be(s, chanid);
482
483         s_mark_end(s);
484         iso_send(s);
485 }
486
487 /* Initialise an MCS transport data packet */
488 STREAM
489 mcs_init(int length)
490 {
491         STREAM s;
492
493         s = iso_init(length + 8);
494         s_push_layer(s, mcs_hdr, 8);
495
496         return s;
497 }
498
499 /* Send an MCS transport data packet to a specific channel */
500 void
501 mcs_send_to_channel(STREAM s, uint16 channel)
502 {
503         uint16 length;
504
505         s_pop_layer(s, mcs_hdr);
506         length = s->end - s->p - 8;
507         length |= 0x8000;
508
509         out_uint8(s, (MCS_SDIN << 2));
510         out_uint16_be(s, g_mcs_userid);
511         out_uint16_be(s, channel);
512         out_uint8(s, 0x70);     /* flags */
513         out_uint16_be(s, length);
514
515         iso_send(s);
516 }
517
518 /* Send an MCS transport data packet to the global channel */
519 void
520 mcs_send(STREAM s)
521 {
522         mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
523 }
524
525 /* Receive an MCS transport data packet */
526 STREAM
527 mcs_recv(uint16 * channel)
528 {
529         uint8 opcode, appid, length, userid;
530         STREAM s;
531
532         s = iso_recv();
533         if (s == NULL)
534                 return NULL;
535
536         in_uint8(s, opcode);
537         appid = opcode >> 2;
538
539         switch (appid) {
540         case MCS_SDRQ:
541                 in_uint8s(s, 2);        /* userid */
542                 in_uint16_be(s, *channel);
543                 in_uint8s(s, 1);        /* flags */
544                 in_uint8(s, length);
545                 if (length & 0x80)
546                         in_uint8s(s, 1);        /* second byte of length */
547
548                 return s;
549         case MCS_DPUM:
550                 printf("Received DPUM (?)\n");
551                 return NULL;
552         case MCS_EDRQ:
553                 // Erect Domain (ignore)
554                 printf("Received EDrq\n");
555                 return NULL;
556         case MCS_AURQ:
557                 // Attach User Request, respond with AUcf (Attach User Confirm)
558                 printf("Received AUrq, sending AUcf\n");
559                 mcs_send_aucf(0);
560                 return NULL;
561         case MCS_CJRQ:
562                 // Channel Join Request, respond with CJcf (Channel Join Confirm);
563                 in_uint16_be(s, userid);
564                 in_uint16_be(s, *channel);
565                 printf("Received CJrq for channel %hu, sending CJcf\n", *channel);
566                 mcs_send_cjcf(userid, *channel);
567                 return NULL;
568         default:
569                 error("expected data, got %d\n", opcode);
570                 return NULL;
571         }
572
573 }
574
575 /* Disconnect from the MCS layer */
576 void
577 mcs_disconnect(void)
578 {
579         iso_disconnect();
580 }