ReactOS  0.4.12-dev-18-gf469aca
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 
24 extern RD_BOOL g_encryption;
28 
30 
31 extern char *g_sc_csp_name;
32 extern char *g_sc_reader_name;
33 extern char *g_sc_card_name;
34 extern char *g_sc_container_name;
35 
36 
37 /* Send a self-contained ISO PDU */
38 static 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 */
50  out_uint8(s, code);
51  out_uint16(s, 0); /* dst_ref */
52  out_uint16(s, 0); /* src_ref */
53  out_uint8(s, 0); /* class */
54 
55  s_mark_end(s);
56  tcp_send(s);
57 }
58 
59 static 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="));
81  out_uint8p(s, username, strlen(username));
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 
95  s_mark_end(s);
96  tcp_send(s);
97 }
98 
99 /* Receive a message on the ISO layer, return code */
100 static STREAM
102 {
103  STREAM s;
104  uint16 length;
105  uint8 version;
106 
107  s = tcp_recv(NULL, 4);
108  if (s == NULL)
109  return NULL;
110  in_uint8(s, version);
111  if (rdpver != NULL)
112  *rdpver = version;
113  if (version == 3)
114  {
115  in_uint8s(s, 1); /* pad */
116  in_uint16_be(s, length);
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 */
149 STREAM
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 */
161 void
163 {
164  uint16 length;
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 */
171  out_uint16_be(s, length);
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 */
181 STREAM
182 iso_recv(uint8 * rdpver)
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 */
202 RD_BOOL
203 iso_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 
230  iso_send_connection_request(username, neg_proto);
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);
239  tcp_disconnect();
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);
254  in_uint16(s, length);
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;
274  case INCONSISTENT_FLAGS:
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 
287  tcp_disconnect();
288 
289  if (retry_without_neg)
290  {
291  fprintf(stderr,
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  {
303  tcp_disconnect();
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 */
315  tcp_disconnect();
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  {
329  if (!cssp_connect(server, username, domain, password, s))
330  {
331  /* failed to connect using cssp, let retry with plain TLS */
332  tcp_disconnect();
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  {
348  tcp_disconnect();
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 */
361 void
363 {
365  tcp_disconnect();
366 }
367 
368 /* reset the state to support reconnecting */
369 void
371 {
373  tcp_reset_state();
374 }
#define out_uint8p(s, v, n)
Definition: parse.h:93
static STREAM iso_recv_msg(uint8 *code, uint8 *rdpver)
Definition: iso.c:101
static rfbScreenInfoPtr server
Definition: vnc.c:74
RD_BOOL tcp_tls_connect(void)
#define error(str)
Definition: mkdosfs.c:1605
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
unsigned int uint32
Definition: types.h:32
#define s_check_rem(s, n)
Definition: parse.h:43
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define out_uint16(s, v)
Definition: parse.h:84
static RD_BOOL g_negotiate_rdp_protocol
Definition: iso.c:29
static void iso_send_msg(uint8 code)
Definition: iso.c:39
void tcp_send(STREAM s)
Definition: tcp.c:270
#define out_uint8(s, v)
Definition: parse.h:92
void iso_disconnect(void)
Definition: iso.c:362
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
static void iso_send_connection_request(char *username, uint32 neg_proto)
Definition: iso.c:60
#define s_pop_layer(s, h)
Definition: parse.h:40
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
RD_BOOL g_encryption
Definition: uimain.c:40
STREAM tcp_init(uint32 maxlen)
Definition: tcp.c:82
char * g_sc_reader_name
#define in_uint8s(s, n)
Definition: parse.h:91
char * g_sc_csp_name
int RD_BOOL
Definition: types.h:21
STREAM iso_init(int length)
Definition: iso.c:150
static WCHAR username[]
Definition: url.c:32
#define True
Definition: types.h:24
#define False
Definition: types.h:25
Definition: types.h:44
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
STREAM iso_recv(uint8 *rdpver)
Definition: iso.c:182
void iso_send(STREAM s)
Definition: iso.c:162
unsigned char * end
Definition: parse.h:25
unsigned char uint8
Definition: types.h:28
RD_BOOL tcp_connect(char *server)
Definition: tcp.c:717
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
void tcp_reset_state(void)
Definition: tcp.c:894
GLbitfield flags
Definition: glext.h:7161
#define in_uint32(s, v)
Definition: parse.h:83
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
RD_BOOL g_encryption_initial
Definition: uimain.c:75
RD_BOOL iso_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect, uint32 *selected_protocol)
Definition: iso.c:203
Definition: parse.h:22
T1_FIELD_DICT_PRIVATE password
Definition: t1tokens.h:64
enum _RDP_VERSION RDP_VERSION
GLdouble s
Definition: gl.h:2039
char * g_sc_card_name
int code
Definition: i386-dis.c:3591
#define s_push_layer(s, h, n)
Definition: parse.h:39
void tcp_disconnect(void)
Definition: tcp.c:832
void iso_reset_state(void)
Definition: iso.c:370
unsigned short uint16
Definition: types.h:30
#define in_uint8(s, v)
Definition: parse.h:88
RD_BOOL g_use_password_as_pin
#define in_uint16(s, v)
Definition: parse.h:82
#define next_be(s, v)
Definition: parse.h:97
unsigned char * p
Definition: parse.h:24
#define out_uint16_be(s, v)
Definition: parse.h:77
FILE * stderr
#define out_uint32(s, v)
Definition: parse.h:85
RDP_VERSION g_rdp_version
Definition: uimain.c:74
#define s_mark_end(s)
Definition: parse.h:41
RD_BOOL cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
#define in_uint16_be(s, v)
Definition: parse.h:75
char * g_sc_container_name
#define warning(s)
Definition: debug.h:71