ReactOS 0.4.16-dev-336-gb667d82
iso.c
Go to the documentation of this file.
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 <astrand@cendio.se> for Cendio AB
6 Copyright 2012 Henrik Andersson <hean01@cendio.se> 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#include "precomp.h"
23
28
30
31extern char *g_sc_csp_name;
32extern char *g_sc_reader_name;
33extern char *g_sc_card_name;
34extern char *g_sc_container_name;
35
36
37/* Send a self-contained ISO PDU */
38static void
40{
41 STREAM s;
42
43 s = tcp_init(11);
44
45 out_uint8(s, 3); /* version */
46 out_uint8(s, 0); /* reserved */
47 out_uint16_be(s, 11); /* length */
48
49 out_uint8(s, 6); /* hdrlen */
51 out_uint16(s, 0); /* dst_ref */
52 out_uint16(s, 0); /* src_ref */
53 out_uint8(s, 0); /* class */
54
56 tcp_send(s);
57}
58
59static void
61{
62 STREAM s;
63 int length = 30 + strlen(username);
64
66 length += 8;
67
68 s = tcp_init(length);
69
70 out_uint8(s, 3); /* version */
71 out_uint8(s, 0); /* reserved */
72 out_uint16_be(s, length); /* length */
73
74 out_uint8(s, length - 5); /* hdrlen */
76 out_uint16(s, 0); /* dst_ref */
77 out_uint16(s, 0); /* src_ref */
78 out_uint8(s, 0); /* class */
79
80 out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
82
83 out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
84 out_uint8(s, 0x0a);
85
87 {
88 /* optional rdp protocol negotiation request for RDPv5 */
90 out_uint8(s, 0);
91 out_uint16(s, 8);
92 out_uint32(s, neg_proto);
93 }
94
96 tcp_send(s);
97}
98
99/* Receive a message on the ISO layer, return code */
100static STREAM
102{
103 STREAM s;
106
107 s = tcp_recv(NULL, 4);
108 if (s == NULL)
109 return NULL;
111 if (rdpver != NULL)
112 *rdpver = version;
113 if (version == 3)
114 {
115 in_uint8s(s, 1); /* pad */
117 }
118 else
119 {
120 in_uint8(s, length);
121 if (length & 0x80)
122 {
123 length &= ~0x80;
124 next_be(s, length);
125 }
126 }
127 if (length < 4)
128 {
129 error("Bad packet header\n");
130 return NULL;
131 }
132 s = tcp_recv(s, length - 4);
133 if (s == NULL)
134 return NULL;
135 if (version != 3)
136 return s;
137 in_uint8s(s, 1); /* hdrlen */
138 in_uint8(s, *code);
139 if (*code == ISO_PDU_DT)
140 {
141 in_uint8s(s, 1); /* eot */
142 return s;
143 }
144 in_uint8s(s, 5); /* dst_ref, src_ref, class */
145 return s;
146}
147
148/* Initialise ISO transport data packet */
149STREAM
151{
152 STREAM s;
153
154 s = tcp_init(length + 7);
155 s_push_layer(s, iso_hdr, 7);
156
157 return s;
158}
159
160/* Send an ISO data PDU */
161void
163{
165
166 s_pop_layer(s, iso_hdr);
167 length = s->end - s->p;
168
169 out_uint8(s, 3); /* version */
170 out_uint8(s, 0); /* reserved */
172
173 out_uint8(s, 2); /* hdrlen */
174 out_uint8(s, ISO_PDU_DT); /* code */
175 out_uint8(s, 0x80); /* eot */
176
177 tcp_send(s);
178}
179
180/* Receive ISO transport data packet */
181STREAM
183{
184 STREAM s;
185 uint8 code = 0;
186
187 s = iso_recv_msg(&code, rdpver);
188 if (s == NULL)
189 return NULL;
190 if (rdpver != NULL)
191 if (*rdpver != 3)
192 return s;
193 if (code != ISO_PDU_DT)
194 {
195 error("expected DT, got 0x%x\n", code);
196 return NULL;
197 }
198 return s;
199}
200
201/* Establish a connection up to the ISO layer */
203iso_connect(char *server, char *username, char *domain, char *password,
204 RD_BOOL reconnect, uint32 * selected_protocol)
205{
206 STREAM s;
207 uint8 code;
208 uint32 neg_proto;
209
211
212 neg_proto = PROTOCOL_SSL;
213
214#ifdef WITH_CREDSSP
216 neg_proto |= PROTOCOL_HYBRID;
218 neg_proto |= PROTOCOL_HYBRID;
219 else
220 warning("Disables CredSSP due to missing smartcard information for SSO.\n");
221#endif
222
223 retry:
224 *selected_protocol = PROTOCOL_RDP;
225 code = 0;
226
227 if (!tcp_connect(server))
228 return False;
229
231
232 s = iso_recv_msg(&code, NULL);
233 if (s == NULL)
234 return False;
235
236 if (code != ISO_PDU_CC)
237 {
238 error("expected CC, got 0x%x\n", code);
240 return False;
241 }
242
243 if (g_rdp_version >= RDP_V5 && s_check_rem(s, 8))
244 {
245 /* handle RDP_NEG_REQ response */
246 const char *reason = NULL;
247
248 uint8 type = 0, flags = 0;
249 uint16 length = 0;
250 uint32 data = 0;
251
252 in_uint8(s, type);
253 in_uint8(s, flags);
255 in_uint32(s, data);
256
257 if (type == RDP_NEG_FAILURE)
258 {
259 RD_BOOL retry_without_neg = False;
260
261 switch (data)
262 {
264 reason = "SSL with user authentication required by server";
265 break;
267 reason = "SSL not allowed by server";
268 retry_without_neg = True;
269 break;
271 reason = "no valid authentication certificate on server";
272 retry_without_neg = True;
273 break;
275 reason = "inconsistent negotiation flags";
276 break;
278 reason = "SSL required by server";
279 break;
281 reason = "CredSSP required by server";
282 break;
283 default:
284 reason = "unknown reason";
285 }
286
288
289 if (retry_without_neg)
290 {
292 "Failed to negotiate protocol, retrying with plain RDP.\n");
294 goto retry;
295 }
296
297 fprintf(stderr, "Failed to connect, %s.\n", reason);
298 return False;
299 }
300
301 if (type != RDP_NEG_RSP)
302 {
304 error("Expected RDP_NEG_RSP, got type = 0x%x\n", type);
305 return False;
306 }
307
308 /* handle negotiation response */
309 if (data == PROTOCOL_SSL)
310 {
311#ifdef WITH_SSL
312 if (!tcp_tls_connect())
313 {
314 /* failed to connect using cssp, let retry with plain TLS */
316 neg_proto = PROTOCOL_RDP;
317 goto retry;
318 }
319 /* do not use encryption when using TLS */
321 fprintf(stderr, "Connection established using SSL.\n");
322#else /* WITH_SSL */
323 fprintf(stderr, "SSL not compiled in.\n");
324#endif /* WITH_SSL */
325 }
326#ifdef WITH_CREDSSP
327 else if (data == PROTOCOL_HYBRID)
328 {
330 {
331 /* failed to connect using cssp, let retry with plain TLS */
333 neg_proto = PROTOCOL_SSL;
334 goto retry;
335 }
336
337 /* do not use encryption when using TLS */
338 fprintf(stderr, "Connection established using CredSSP.\n");
340 }
341#endif
342 else if (data == PROTOCOL_RDP)
343 {
344 fprintf(stderr, "Connection established using plain RDP.\n");
345 }
346 else if (data != PROTOCOL_RDP)
347 {
349 error("Unexpected protocol in negotiation response, got data = 0x%x.\n",
350 data);
351 return False;
352 }
353 if (length || flags) {}
354
355 *selected_protocol = data;
356 }
357 return True;
358}
359
360/* Disconnect from the ISO layer */
361void
363{
366}
367
368/* reset the state to support reconnecting */
369void
371{
374}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
@ PROTOCOL_SSL
Definition: constants.h:47
@ PROTOCOL_HYBRID
Definition: constants.h:48
@ PROTOCOL_RDP
Definition: constants.h:46
@ RDP_NEG_REQ
Definition: constants.h:39
@ RDP_NEG_FAILURE
Definition: constants.h:41
@ RDP_NEG_RSP
Definition: constants.h:40
@ SSL_CERT_NOT_ON_SERVER
Definition: constants.h:55
@ HYBRID_REQUIRED_BY_SERVER
Definition: constants.h:57
@ SSL_REQUIRED_BY_SERVER
Definition: constants.h:53
@ SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER
Definition: constants.h:58
@ INCONSISTENT_FLAGS
Definition: constants.h:56
@ SSL_NOT_ALLOWED_BY_SERVER
Definition: constants.h:54
@ ISO_PDU_CC
Definition: constants.h:30
@ ISO_PDU_CR
Definition: constants.h:29
@ ISO_PDU_DT
Definition: constants.h:32
@ ISO_PDU_DR
Definition: constants.h:31
char * g_sc_csp_name
static void iso_send_msg(uint8 code)
Definition: iso.c:39
static STREAM iso_recv_msg(uint8 *code, uint8 *rdpver)
Definition: iso.c:101
static void iso_send_connection_request(char *username, uint32 neg_proto)
Definition: iso.c:60
void iso_reset_state(void)
Definition: iso.c:370
RD_BOOL iso_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect, uint32 *selected_protocol)
Definition: iso.c:203
RD_BOOL g_encryption_initial
Definition: uimain.c:75
RD_BOOL g_encryption
Definition: uimain.c:40
char * g_sc_reader_name
RD_BOOL g_use_password_as_pin
static RD_BOOL g_negotiate_rdp_protocol
Definition: iso.c:29
RDP_VERSION g_rdp_version
Definition: uimain.c:74
void iso_send(STREAM s)
Definition: iso.c:162
char * g_sc_container_name
char * g_sc_card_name
STREAM iso_init(int length)
Definition: iso.c:150
void iso_disconnect(void)
Definition: iso.c:362
STREAM iso_recv(uint8 *rdpver)
Definition: iso.c:182
#define s_mark_end(s)
Definition: parse.h:41
#define in_uint32(s, v)
Definition: parse.h:83
#define s_pop_layer(s, h)
Definition: parse.h:40
#define out_uint8(s, v)
Definition: parse.h:92
#define s_push_layer(s, h, n)
Definition: parse.h:39
#define out_uint16_be(s, v)
Definition: parse.h:77
#define in_uint8s(s, n)
Definition: parse.h:91
#define next_be(s, v)
Definition: parse.h:97
#define in_uint8(s, v)
Definition: parse.h:88
#define in_uint16_be(s, v)
Definition: parse.h:75
#define s_check_rem(s, n)
Definition: parse.h:43
#define out_uint8p(s, v, n)
Definition: parse.h:93
#define out_uint32(s, v)
Definition: parse.h:85
#define in_uint16(s, v)
Definition: parse.h:82
#define out_uint16(s, v)
Definition: parse.h:84
void tcp_disconnect(void)
Definition: tcp.c:832
void tcp_send(STREAM s)
Definition: tcp.c:270
void tcp_reset_state(void)
Definition: tcp.c:894
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
RD_BOOL tcp_tls_connect(void)
RD_BOOL tcp_connect(char *server)
Definition: tcp.c:717
STREAM tcp_init(uint32 maxlen)
Definition: tcp.c:82
RD_BOOL cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
@ RDP_V5
Definition: types.h:44
enum _RDP_VERSION RDP_VERSION
int RD_BOOL
Definition: types.h:21
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
#define NULL
Definition: types.h:112
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
static const WCHAR version[]
Definition: asmname.c:66
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define error(str)
Definition: mkdosfs.c:1605
static WCHAR password[]
Definition: url.c:33
static WCHAR username[]
Definition: url.c:32
#define warning(s)
Definition: debug.h:83
Definition: inflate.c:139
Definition: cookie.c:42
Definition: parse.h:23
static rfbScreenInfoPtr server
Definition: vnc.c:74