]> git.sesse.net Git - rdpsrv/blob - mcs.c
6c5bbb77ef4e3209de3dca695d520dd92a8e7499
[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, 1); // 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                 const 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                 printf("Loaded private key (%u bytes)\n", sizeof(private_key));
404         }
405 }
406
407 /* Send an EDrq message (ASN.1 PER) */
408 static void
409 mcs_send_edrq(void)
410 {
411         STREAM s;
412
413         s = iso_init(5);
414
415         out_uint8(s, (MCS_EDRQ << 2));
416         out_uint16_be(s, 1);    /* height */
417         out_uint16_be(s, 1);    /* interval */
418
419         s_mark_end(s);
420         iso_send(s);
421 }
422
423 /* Send an AUrq message (ASN.1 PER) */
424 static void
425 mcs_send_aurq(void)
426 {
427         STREAM s;
428
429         s = iso_init(1);
430
431         out_uint8(s, (MCS_AURQ << 2));
432
433         s_mark_end(s);
434         iso_send(s);
435 }
436
437 /* Send a AUcf message (ASN.1 PER) */
438 static void
439 mcs_send_aucf(uint16 mcs_userid)
440 {
441         STREAM s;
442
443         s = iso_init(4);
444
445         out_uint8(s, (MCS_AUCF << 2) | 2);  // | 2 = send user ID
446         out_uint8(s, 0);  // success
447         out_uint16_be(s, 6);
448         
449         s_mark_end(s);
450         iso_send(s);
451 }
452
453 /* Send a CJrq message (ASN.1 PER) */
454 static void
455 mcs_send_cjrq(uint16 chanid)
456 {
457         STREAM s;
458
459         DEBUG_RDP5(("Sending CJRQ for channel #%d\n", chanid));
460
461         s = iso_init(5);
462
463         out_uint8(s, (MCS_CJRQ << 2));
464         out_uint16_be(s, g_mcs_userid);
465         out_uint16_be(s, chanid);
466
467         s_mark_end(s);
468         iso_send(s);
469 }
470
471 /* Expect a CJcf message (ASN.1 PER) */
472 static void
473 mcs_send_cjcf(uint16 userid, uint16 chanid)
474 {
475         STREAM s;
476
477         s = iso_init(8);
478
479         out_uint8(s, (MCS_CJCF << 2) | 2);
480         out_uint8(s, 0); // success
481         out_uint16_be(s, 6);
482         out_uint16_be(s, chanid);
483         out_uint16_be(s, chanid);
484
485         s_mark_end(s);
486         iso_send(s);
487 }
488
489 /* Initialise an MCS transport data packet */
490 STREAM
491 mcs_init(int length)
492 {
493         STREAM s;
494
495         s = iso_init(length + 8);
496         s_push_layer(s, mcs_hdr, 8);
497
498         return s;
499 }
500
501 /* Send an MCS transport data packet to a specific channel */
502 void
503 mcs_send_to_channel(STREAM s, uint16 channel)
504 {
505         uint16 length;
506
507         s_pop_layer(s, mcs_hdr);
508         length = s->end - s->p - 8;
509         length |= 0x8000;
510
511         out_uint8(s, (MCS_SDIN << 2));
512         out_uint16_be(s, g_mcs_userid);
513         out_uint16_be(s, channel);
514         out_uint8(s, 0x70);     /* flags */
515         out_uint16_be(s, length);
516
517         iso_send(s);
518 }
519
520 /* Send an MCS transport data packet to the global channel */
521 void
522 mcs_send(STREAM s)
523 {
524         mcs_send_to_channel(s, MCS_GLOBAL_CHANNEL);
525 }
526
527 /* Receive an MCS transport data packet */
528 STREAM
529 mcs_recv(uint16 * channel)
530 {
531         uint8 opcode, appid, length, userid;
532         STREAM s;
533
534         s = iso_recv();
535         if (s == NULL)
536                 return NULL;
537
538         in_uint8(s, opcode);
539         appid = opcode >> 2;
540
541         switch (appid) {
542         case MCS_SDRQ:
543                 in_uint8s(s, 2);        /* userid */
544                 in_uint16_be(s, *channel);
545                 in_uint8s(s, 1);        /* flags */
546                 in_uint8(s, length);
547                 if (length & 0x80)
548                         in_uint8s(s, 1);        /* second byte of length */
549
550                 return s;
551         case MCS_DPUM:
552                 printf("Received DPUM (?)\n");
553                 return NULL;
554         case MCS_EDRQ:
555                 // Erect Domain (ignore)
556                 printf("Received EDrq\n");
557                 return NULL;
558         case MCS_AURQ:
559                 // Attach User Request, respond with AUcf (Attach User Confirm)
560                 printf("Received AUrq, sending AUcf\n");
561                 mcs_send_aucf(0);
562                 return NULL;
563         case MCS_CJRQ:
564                 // Channel Join Request, respond with CJcf (Channel Join Confirm);
565                 in_uint16_be(s, userid);
566                 in_uint16_be(s, *channel);
567                 printf("Received CJrq for channel %hu, sending CJcf\n", *channel);
568                 mcs_send_cjcf(userid, *channel);
569                 return NULL;
570         default:
571                 error("expected data, got %d\n", opcode);
572                 return NULL;
573         }
574
575 }
576
577 /* Disconnect from the MCS layer */
578 void
579 mcs_disconnect(void)
580 {
581         iso_disconnect();
582 }