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