1
/* -*- c-basic-offset: 8 -*-
2
rdesktop: A Remote Desktop Protocol client.
3
Protocol services - ISO layer
4
Copyright (C) Matthew Chapman 1999-2008
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.
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.
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.
29
/* TPKT from T123 - aka ISO DP 8073 */
31
/* Output TPKT header for length length.
32
* Length should include the TPKT header (4 bytes) */
34
tpkt_output_header(STREAM s, int length)
36
out_uint8(s, 3); /* version */
37
out_uint8(s, 0); /* reserved */
38
out_uint16_be(s, length); /* length */
41
/* Try to read TPKT header for X.224 from stream and return length
42
* (including the 4 bytes TPKT header already read).
43
* If not possible then return untouched stream and length -1. */
45
tpkt_input_header(STREAM s)
47
if (*s->p == 3) /* Peeking is less ugly than rewinding */
54
in_uint8(s, reserved);
55
in_uint16_be(s, length);
58
return -1; /* Probably Fast-Path */
61
/* Output and send 7 bytes X.224 headers for
62
* Client X.224 Connection Request TPDU (X224_TPDU_CONNECTION_REQUEST)
63
* Server X.224 Connection Confirm TPDU
64
* FIXME: is this also suitable for X224_TPDU_DISCONNECT_REQUEST ??? */
66
x224_send_dst_src_class(rdpIso * iso, uint8 code)
70
s = tcp_init(iso->tcp, 11);
72
tpkt_output_header(s, 11);
74
out_uint8(s, 6); /* length indicator */
76
out_uint16_le(s, 0); /* dst_ref */
77
out_uint16_le(s, 0); /* src_ref */
78
out_uint8(s, 0); /* class */
81
tcp_send(iso->tcp, s);
84
/* Output and send X.224 Connection Request TPDU with routing for username */
86
x224_send_connection_request(rdpIso * iso, char *username)
89
int length = 30 + strlen(username);
91
if (iso->mcs->sec->tls)
95
* negotiation_state is used so that tcp_recv() will be able to make
96
* the distinction between an unexpected disconnection and a
97
* disconnection that is to be expected if negotation fails, such as
98
* when the client claims to support TLS with NLA but the server only
99
* supports the legacy encryption.
102
/* FIXME: Use x224_send_dst_src_class */
103
s = tcp_init(iso->tcp, length);
105
tpkt_output_header(s, length);
107
/* X.224 Connection Request (CR) TPDU */
108
out_uint8(s, length - 5); /* length indicator */
109
out_uint8(s, X224_TPDU_CONNECTION_REQUEST);
110
out_uint16_le(s, 0); /* dst_ref */
111
out_uint16_le(s, 0); /* src_ref */
112
out_uint8(s, 0); /* class */
115
out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
116
out_uint8p(s, username, strlen(username));
119
out_uint8(s, 0x0D); /* CR */
120
out_uint8(s, 0x0A); /* LF */
122
if (iso->mcs->sec->tls)
124
/* When using TLS + NLA, the RDP_NEG_DATA field should be present */
125
out_uint8(s, TYPE_RDP_NEG_REQ);
126
out_uint8(s, 0x00); /* flags, must be set to zero */
127
out_uint16_le(s, 8); /* RDP_NEG_DATA length (8) */
128
out_uint32_le(s, PROTOCOL_HYBRID | PROTOCOL_SSL); /* requestedProtocols */
132
tcp_send(iso->tcp, s);
135
/* Process Negotiation Response from Connection Confirm payload
136
* Return selected protocol */
137
static uint32 /* or enum RDP_NEG_PROTOCOLS */
138
rdp_process_negotiation_response(rdpIso * iso, STREAM s)
142
uint32 selectedProtocol;
145
in_uint16_le(s, length);
146
in_uint32_le(s, selectedProtocol);
148
if (iso->mcs->sec->tls)
150
switch (selectedProtocol)
153
printf("Selected PROTOCOL_RDP Security\n");
156
printf("Selected PROTOCOL_SSL Security\n");
158
case PROTOCOL_HYBRID:
159
printf("Selected PROTOCOL_HYBRID Security\n");
162
printf("Error: Unknown protocol security\n");
167
return selectedProtocol;
170
/* Process Negotiation Failure from Connection Confirm payload */
172
rdp_process_negotiation_failure(rdpIso * iso, STREAM s)
179
in_uint16_le(s, length);
180
in_uint32_le(s, failureCode);
182
if (iso->mcs->sec->tls)
186
case SSL_REQUIRED_BY_SERVER:
187
printf("Error: SSL_REQUIRED_BY_SERVER\n");
189
case SSL_NOT_ALLOWED_BY_SERVER:
190
printf("Error: SSL_NOT_ALLOWED_BY_SERVER\n");
192
case SSL_CERT_NOT_ON_SERVER:
193
printf("Error: SSL_CERT_NOT_ON_SERVER\n");
195
case INCONSISTENT_FLAGS:
196
printf("Error: INCONSISTENT_FLAGS\n");
198
case HYBRID_REQUIRED_BY_SERVER:
199
printf("Error: HYBRID_REQUIRED_BY_SERVER\n");
202
printf("Error: Unknown protocol security error %d\n", failureCode);
208
/* Receive an X.224 TPDU */
210
x224_recv(rdpIso * iso, STREAM s, int length, uint8 * pcode)
212
uint8 lengthIndicator;
217
s = tcp_recv(iso->tcp, s, length - 4);
222
/* X.224 TPDU Header */
223
in_uint8(s, lengthIndicator);
226
subcode = code & 0x0F; /* get the lower nibble */
227
code &= 0xF0; /* take out lower nibble */
231
if (code == X224_TPDU_DATA)
233
in_uint8s(s, 1); /* EOT */
237
/* dst-ref (2 bytes) */
238
/* src-ref (2 bytes) */
239
/* class option (1 byte) */
244
/* Connection Request */
245
case X224_TPDU_CONNECTION_REQUEST:
246
printf("X224_TPDU_CONNECTION_REQUEST\n");
249
/* Connection Confirm */
250
case X224_TPDU_CONNECTION_CONFIRM:
251
printf("X224_TPDU_CONNECTION_CONFIRM\n");
254
/* Disconnect Request */
255
case X224_TPDU_DISCONNECT_REQUEST:
256
printf("X224_TPDU_DISCONNECT_REQUEST\n");
261
printf("X224_TPDU_DATA\n");
265
case X224_TPDU_ERROR:
266
printf("X224_TPDU_ERROR\n");
270
/* According to X.224 13.4 and [MS-RDPBCGR] 2.2.1.2, the rdpNegData field is optional
271
and its length is included in the X.224 length indicator */
272
if (lengthIndicator > 6)
274
in_uint8(s, type); /* Type */
277
case TYPE_RDP_NEG_RSP:
278
printf("TYPE_RDP_NEG_RSP\n");
279
rdp_process_negotiation_response(iso, s);
281
case TYPE_RDP_NEG_FAILURE:
282
printf("TYPE_RDP_NEG_FAILURE\n");
283
rdp_process_negotiation_failure(iso, s);
291
/* Receive a packet from tcp and return stream.
292
* If no ptype then only TPKT header with X.224 is accepted.
293
* If ptype then Fast-Path packets are accepted too.
294
* Return NULL on error. */
296
tpkt_recv(rdpIso * iso, uint8 * pcode, isoRecvType * ptype)
301
s = tcp_recv(iso->tcp, NULL, 4);
306
length = tpkt_input_header(s);
310
/* Valid TPKT header, payload is X.224 TPDU */
312
*ptype = ISO_RECV_X224;
314
return x224_recv(iso, s, length, pcode);
316
else if (ptype != NULL)
318
/* Fast-Path header */
321
in_uint8(s, fpInputHeader);
322
*ptype = (fpInputHeader & 0x80) ? ISO_RECV_FAST_PATH_ENCRYPTED : ISO_RECV_FAST_PATH;
330
s = tcp_recv(iso->tcp, s, length - 4);
333
return NULL; /* Fast-Path not allowed */
337
iso_negotiate_encryption(rdpIso * iso, char *username)
341
if (iso->mcs->sec->tls == 0)
343
/* We do no use TLS + NLA, so we won't attempt to negotiate */
345
iso->mcs->sec->negotiation_state = 2;
346
x224_send_connection_request(iso, username);
348
/* Receive negotiation response */
349
if (tpkt_recv(iso, &code, NULL) == NULL)
354
/* first negotiation attempt */
355
iso->mcs->sec->negotiation_state = 1;
357
x224_send_connection_request(iso, username);
359
/* Attempt to receive negotiation response */
360
if (tpkt_recv(iso, &code, NULL) == NULL)
362
if (iso->mcs->sec->negotiation_state == -1)
364
/* Negotiation failure, downgrade encryption and try again */
366
iso->mcs->sec->tls = 0;
368
/* second negotiation attempt */
369
iso->mcs->sec->negotiation_state = 2;
371
x224_send_connection_request(iso, username);
373
/* Receive negotiation response */
374
if (tpkt_recv(iso, &code, NULL) == NULL)
383
/* Receive a message on the ISO layer, return code */
385
iso_recv_msg(rdpIso * iso, uint8 * code, isoRecvType * ptype)
387
return tpkt_recv(iso, code, ptype);
390
/* Initialise ISO transport data packet */
392
iso_init(rdpIso * iso, int length)
396
s = tcp_init(iso->tcp, length + 7);
397
s_push_layer(s, iso_hdr, 7);
402
/* Initialise fast path data packet */
404
iso_fp_init(rdpIso * iso, int length)
408
s = tcp_init(iso->tcp, length + 3);
409
s_push_layer(s, iso_hdr, 3);
413
/* Send an ISO data PDU */
415
iso_send(rdpIso * iso, STREAM s)
419
s_pop_layer(s, iso_hdr);
420
length = s->end - s->p;
422
out_uint8(s, 3); /* version */
423
out_uint8(s, 0); /* reserved */
424
out_uint16_be(s, length);
426
out_uint8(s, 2); /* hdrlen */
427
out_uint8(s, X224_TPDU_DATA); /* code */
428
out_uint8(s, 0x80); /* eot */
430
tcp_send(iso->tcp, s);
433
/* Send an fast path data PDU */
435
iso_fp_send(rdpIso * iso, STREAM s, uint32 flags)
441
fp_flags = (1 << 2) | 0; /* one event, fast path */
442
if (flags & SEC_ENCRYPT)
444
fp_flags |= 2 << 6; /* FASTPATH_INPUT_ENCRYPTED */
446
s_pop_layer(s, iso_hdr);
447
len = (int) (s->end - s->p);
448
out_uint8(s, fp_flags);
451
out_uint16_be(s, len | 0x8000);
455
/* copy the bits up to pack and save 1 byte */
456
for (index = 3; index < len; index++)
458
s->data[index - 1] = s->data[index];
464
tcp_send(iso->tcp, s);
467
/* Receive ISO transport data packet
468
* If ptype is NULL then only X224 is accepted */
470
iso_recv(rdpIso * iso, isoRecvType * ptype)
475
s = iso_recv_msg(iso, &code, ptype);
480
if ((ptype != NULL) &&
481
(*ptype == ISO_RECV_X224) &&
482
(code != X224_TPDU_DATA))
484
ui_error(iso->mcs->sec->rdp->inst, "expected X224_TPDU_DATA, got 0x%x\n", code);
491
/* Establish a connection up to the ISO layer */
493
iso_connect(rdpIso * iso, char *server, char *username, int port)
495
if (!tcp_connect(iso->tcp, server, port))
498
return iso_negotiate_encryption(iso, username);
501
/* Establish a reconnection up to the ISO layer */
503
iso_reconnect(rdpIso * iso, char *server, int port)
507
if (!tcp_connect(iso->tcp, server, port))
510
x224_send_dst_src_class(iso, X224_TPDU_CONNECTION_REQUEST);
512
if (iso_recv_msg(iso, &code, NULL) == NULL)
515
if (code != X224_TPDU_CONNECTION_CONFIRM)
517
ui_error(iso->mcs->sec->rdp->inst,
518
"expected X224_TPDU_CONNECTION_CONFIRM, got 0x%x\n", code);
519
tcp_disconnect(iso->tcp);
526
/* Disconnect from the ISO layer */
528
iso_disconnect(rdpIso * iso)
530
x224_send_dst_src_class(iso, X224_TPDU_DISCONNECT_REQUEST);
531
tcp_disconnect(iso->tcp);
534
/* reset the state to support reconnecting */
536
iso_reset_state(rdpIso * iso)
538
tcp_reset_state(iso->tcp);
542
iso_new(struct rdp_mcs *mcs)
546
self = (rdpIso *) xmalloc(sizeof(rdpIso));
550
memset(self, 0, sizeof(rdpIso));
552
self->tcp = tcp_new(self);
559
iso_free(rdpIso * iso)