VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/iso.c@ 78352

Last change on this file since 78352 was 55123, checked in by vboxsync, 10 years ago

rdesktop 1.8.3 modified for VBox

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.3 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - ISO layer
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
5 Copyright 2005-2011 Peter Astrand <[email protected]> for Cendio AB
6 Copyright 2012 Henrik Andersson <[email protected]> for Cendio AB
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22/*
23 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
24 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
25 * the General Public License version 2 (GPLv2) at this time for any software where
26 * a choice of GPL license versions is made available with the language indicating
27 * that GPLv2 or any later version may be used, or where a choice of which version
28 * of the GPL is applied is otherwise unspecified.
29 */
30
31#include "rdesktop.h"
32
33extern RD_BOOL g_encryption;
34extern RD_BOOL g_encryption_initial;
35extern RDP_VERSION g_rdp_version;
36extern RD_BOOL g_use_password_as_pin;
37
38static RD_BOOL g_negotiate_rdp_protocol = True;
39
40extern char *g_sc_csp_name;
41extern char *g_sc_reader_name;
42extern char *g_sc_card_name;
43extern char *g_sc_container_name;
44
45
46/* Send a self-contained ISO PDU */
47static void
48iso_send_msg(uint8 code)
49{
50 STREAM s;
51
52 s = tcp_init(11);
53
54 out_uint8(s, 3); /* version */
55 out_uint8(s, 0); /* reserved */
56 out_uint16_be(s, 11); /* length */
57
58 out_uint8(s, 6); /* hdrlen */
59 out_uint8(s, code);
60 out_uint16(s, 0); /* dst_ref */
61 out_uint16(s, 0); /* src_ref */
62 out_uint8(s, 0); /* class */
63
64 s_mark_end(s);
65 tcp_send(s);
66}
67
68static void
69iso_send_connection_request(char *username, uint32 neg_proto)
70{
71 STREAM s;
72 int length = 30 + strlen(username);
73
74 if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
75 length += 8;
76
77 s = tcp_init(length);
78
79 out_uint8(s, 3); /* version */
80 out_uint8(s, 0); /* reserved */
81 out_uint16_be(s, length); /* length */
82
83 out_uint8(s, length - 5); /* hdrlen */
84 out_uint8(s, ISO_PDU_CR);
85 out_uint16(s, 0); /* dst_ref */
86 out_uint16(s, 0); /* src_ref */
87 out_uint8(s, 0); /* class */
88
89 out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
90 out_uint8p(s, username, strlen(username));
91
92 out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
93 out_uint8(s, 0x0a);
94
95 if (g_rdp_version >= RDP_V5 && g_negotiate_rdp_protocol)
96 {
97 /* optional rdp protocol negotiation request for RDPv5 */
98 out_uint8(s, RDP_NEG_REQ);
99 out_uint8(s, 0);
100 out_uint16(s, 8);
101 out_uint32(s, neg_proto);
102 }
103
104 s_mark_end(s);
105 tcp_send(s);
106}
107
108/* Receive a message on the ISO layer, return code */
109static STREAM
110iso_recv_msg(uint8 * code, uint8 * rdpver)
111{
112 STREAM s;
113 uint16 length;
114 uint8 version;
115
116 s = tcp_recv(NULL, 4);
117 if (s == NULL)
118 return NULL;
119 in_uint8(s, version);
120 if (rdpver != NULL)
121 *rdpver = version;
122 if (version == 3)
123 {
124 in_uint8s(s, 1); /* pad */
125 in_uint16_be(s, length);
126 }
127 else
128 {
129 in_uint8(s, length);
130 if (length & 0x80)
131 {
132 length &= ~0x80;
133 next_be(s, length);
134 }
135 }
136 if (length < 4)
137 {
138 error("Bad packet header\n");
139 return NULL;
140 }
141 s = tcp_recv(s, length - 4);
142 if (s == NULL)
143 return NULL;
144 if (version != 3)
145 return s;
146 in_uint8s(s, 1); /* hdrlen */
147 in_uint8(s, *code);
148 if (*code == ISO_PDU_DT)
149 {
150 in_uint8s(s, 1); /* eot */
151 return s;
152 }
153 in_uint8s(s, 5); /* dst_ref, src_ref, class */
154 return s;
155}
156
157/* Initialise ISO transport data packet */
158STREAM
159iso_init(int length)
160{
161 STREAM s;
162
163 s = tcp_init(length + 7);
164 s_push_layer(s, iso_hdr, 7);
165
166 return s;
167}
168
169/* Send an ISO data PDU */
170void
171iso_send(STREAM s)
172{
173 uint16 length;
174
175 s_pop_layer(s, iso_hdr);
176 length = s->end - s->p;
177
178 out_uint8(s, 3); /* version */
179 out_uint8(s, 0); /* reserved */
180 out_uint16_be(s, length);
181
182 out_uint8(s, 2); /* hdrlen */
183 out_uint8(s, ISO_PDU_DT); /* code */
184 out_uint8(s, 0x80); /* eot */
185
186 tcp_send(s);
187}
188
189/* Receive ISO transport data packet */
190STREAM
191iso_recv(uint8 * rdpver)
192{
193 STREAM s;
194 uint8 code = 0;
195
196 s = iso_recv_msg(&code, rdpver);
197 if (s == NULL)
198 return NULL;
199 if (rdpver != NULL)
200 if (*rdpver != 3)
201 return s;
202 if (code != ISO_PDU_DT)
203 {
204 error("expected DT, got 0x%x\n", code);
205 return NULL;
206 }
207 return s;
208}
209
210/* Establish a connection up to the ISO layer */
211RD_BOOL
212iso_connect(char *server, char *username, char *domain, char *password,
213 RD_BOOL reconnect, uint32 * selected_protocol)
214{
215 STREAM s;
216 uint8 code;
217 uint32 neg_proto;
218
219 g_negotiate_rdp_protocol = True;
220
221 neg_proto = PROTOCOL_SSL;
222
223#ifdef WITH_CREDSSP
224 if (!g_use_password_as_pin)
225 neg_proto |= PROTOCOL_HYBRID;
226 else if (g_sc_csp_name || g_sc_reader_name || g_sc_card_name || g_sc_container_name)
227 neg_proto |= PROTOCOL_HYBRID;
228 else
229 warning("Disables CredSSP due to missing smartcard information for SSO.\n");
230#endif
231
232 retry:
233 *selected_protocol = PROTOCOL_RDP;
234 code = 0;
235
236 if (!tcp_connect(server))
237 return False;
238
239 iso_send_connection_request(username, neg_proto);
240
241 s = iso_recv_msg(&code, NULL);
242 if (s == NULL)
243 return False;
244
245 if (code != ISO_PDU_CC)
246 {
247 error("expected CC, got 0x%x\n", code);
248 tcp_disconnect();
249 return False;
250 }
251
252 if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
253 {
254 /* handle RDP_NEG_REQ response */
255 const char *reason = NULL;
256
257 uint8 type = 0, flags = 0;
258 uint16 length = 0;
259 uint32 data = 0;
260
261 in_uint8(s, type);
262 in_uint8(s, flags);
263 in_uint16(s, length);
264 in_uint32(s, data);
265
266 if (type == RDP_NEG_FAILURE)
267 {
268 RD_BOOL retry_without_neg = False;
269
270 switch (data)
271 {
272 case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
273 reason = "SSL with user authentication required by server";
274 break;
275 case SSL_NOT_ALLOWED_BY_SERVER:
276 reason = "SSL not allowed by server";
277 retry_without_neg = True;
278 break;
279 case SSL_CERT_NOT_ON_SERVER:
280 reason = "no valid authentication certificate on server";
281 retry_without_neg = True;
282 break;
283 case INCONSISTENT_FLAGS:
284 reason = "inconsistent negotiation flags";
285 break;
286 case SSL_REQUIRED_BY_SERVER:
287 reason = "SSL required by server";
288 break;
289 case HYBRID_REQUIRED_BY_SERVER:
290 reason = "CredSSP required by server";
291 break;
292 default:
293 reason = "unknown reason";
294 }
295
296 tcp_disconnect();
297
298 if (retry_without_neg)
299 {
300 fprintf(stderr,
301 "Failed to negotiate protocol, retrying with plain RDP.\n");
302 g_negotiate_rdp_protocol = False;
303 goto retry;
304 }
305
306 fprintf(stderr, "Failed to connect, %s.\n", reason);
307 return False;
308 }
309
310 if (type != RDP_NEG_RSP)
311 {
312 tcp_disconnect();
313 error("Expected RDP_NEG_RSP, got type = 0x%x\n", type);
314 return False;
315 }
316
317 /* handle negotiation response */
318 if (data == PROTOCOL_SSL)
319 {
320 if (!tcp_tls_connect())
321 {
322 /* failed to connect using cssp, let retry with plain TLS */
323 tcp_disconnect();
324 neg_proto = PROTOCOL_RDP;
325 goto retry;
326 }
327 /* do not use encryption when using TLS */
328 g_encryption = False;
329 fprintf(stderr, "Connection established using SSL.\n");
330 }
331#ifdef WITH_CREDSSP
332 else if (data == PROTOCOL_HYBRID)
333 {
334 if (!cssp_connect(server, username, domain, password, s))
335 {
336 /* failed to connect using cssp, let retry with plain TLS */
337 tcp_disconnect();
338 neg_proto = PROTOCOL_SSL;
339 goto retry;
340 }
341
342 /* do not use encryption when using TLS */
343 fprintf(stderr, "Connection established using CredSSP.\n");
344 g_encryption = False;
345 }
346#endif
347 else if (data == PROTOCOL_RDP)
348 {
349 fprintf(stderr, "Connection established using plain RDP.\n");
350 }
351 else if (data != PROTOCOL_RDP)
352 {
353 tcp_disconnect();
354 error("Unexpected protocol in negotiation response, got data = 0x%x.\n",
355 data);
356 return False;
357 }
358
359 *selected_protocol = data;
360 }
361 return True;
362}
363
364/* Disconnect from the ISO layer */
365void
366iso_disconnect(void)
367{
368 iso_send_msg(ISO_PDU_DR);
369 tcp_disconnect();
370}
371
372/* reset the state to support reconnecting */
373void
374iso_reset_state(void)
375{
376 g_encryption = g_encryption_initial;
377 tcp_reset_state();
378}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette