1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Network Transport Layer
4 *
5 * Copyright 2011 Vic Lee
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <assert.h>
25
26 #include <winpr/crt.h>
27 #include <winpr/synch.h>
28 #include <winpr/print.h>
29 #include <winpr/stream.h>
30 #include <winpr/winsock.h>
31 #include <winpr/crypto.h>
32
33 #include <freerdp/log.h>
34 #include <freerdp/error.h>
35 #include <freerdp/utils/ringbuffer.h>
36
37 #include <openssl/bio.h>
38 #include <time.h>
39 #include <errno.h>
40 #include <fcntl.h>
41
42 #ifndef _WIN32
43 #include <netdb.h>
44 #include <sys/socket.h>
45 #endif /* _WIN32 */
46
47 #ifdef HAVE_VALGRIND_MEMCHECK_H
48 #include <valgrind/memcheck.h>
49 #endif
50
51 #include "tpkt.h"
52 #include "fastpath.h"
53 #include "transport.h"
54 #include "rdp.h"
55 #include "proxy.h"
56
57 #define TAG FREERDP_TAG("core.transport")
58
59 #define BUFFER_SIZE 16384
60
61 #ifdef WITH_GSSAPI
62
63 #include <krb5.h>
64 #include <winpr/library.h>
transport_krb5_check_account(rdpTransport * transport,char * username,char * domain,char * passwd)65 static UINT32 transport_krb5_check_account(rdpTransport* transport, char* username, char* domain,
66 char* passwd)
67 {
68 krb5_error_code ret;
69 krb5_context context = NULL;
70 krb5_principal principal = NULL;
71 char address[256];
72 krb5_ccache ccache;
73 krb5_init_creds_context ctx = NULL;
74 _snprintf(address, sizeof(address), "%s@%s", username, domain);
75
76 /* Create a krb5 library context */
77 if ((ret = krb5_init_context(&context)) != 0)
78 WLog_Print(transport->log, WLOG_ERROR, "krb5_init_context failed with error %d", (int)ret);
79 else if ((ret = krb5_parse_name_flags(context, address, 0, &principal)) != 0)
80 WLog_Print(transport->log, WLOG_ERROR, "krb5_parse_name_flags failed with error %d",
81 (int)ret);
82 /* Find a credential cache with a specified client principal */
83 else if ((ret = krb5_cc_cache_match(context, principal, &ccache)) != 0)
84 {
85 if ((ret = krb5_cc_default(context, &ccache)) != 0)
86 WLog_Print(transport->log, WLOG_ERROR,
87 "krb5 failed to resolve credentials cache with error %d", (int)ret);
88 }
89
90 if (ret != KRB5KDC_ERR_NONE)
91 goto out;
92 /* Create a context for acquiring initial credentials */
93 else if ((ret = krb5_init_creds_init(context, principal, NULL, NULL, 0, NULL, &ctx)) != 0)
94 {
95 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_init returned error %d", (int)ret);
96 goto out;
97 }
98 /* Set a password for acquiring initial credentials */
99 else if ((ret = krb5_init_creds_set_password(context, ctx, passwd)) != 0)
100 {
101 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_set_password returned error %d",
102 ret);
103 goto out;
104 }
105
106 /* Acquire credentials using an initial credential context */
107 ret = krb5_init_creds_get(context, ctx);
108 out:
109
110 switch (ret)
111 {
112 case KRB5KDC_ERR_NONE:
113 break;
114
115 case KRB5_KDC_UNREACH:
116 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_get: KDC unreachable");
117 ret = FREERDP_ERROR_CONNECT_KDC_UNREACHABLE;
118 break;
119
120 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
121 case KRB5KRB_AP_ERR_MODIFIED:
122 case KRB5KDC_ERR_PREAUTH_FAILED:
123 case KRB5_GET_IN_TKT_LOOP:
124 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_get: Password incorrect");
125 ret = FREERDP_ERROR_AUTHENTICATION_FAILED;
126 break;
127
128 case KRB5KDC_ERR_KEY_EXP:
129 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_get: Password has expired");
130 ret = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
131 break;
132
133 case KRB5KDC_ERR_CLIENT_REVOKED:
134 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_get: Password revoked");
135 ret = FREERDP_ERROR_CONNECT_CLIENT_REVOKED;
136 break;
137
138 case KRB5KDC_ERR_POLICY:
139 ret = FREERDP_ERROR_INSUFFICIENT_PRIVILEGES;
140 break;
141
142 default:
143 WLog_Print(transport->log, WLOG_WARN, "krb5_init_creds_get");
144 ret = FREERDP_ERROR_CONNECT_TRANSPORT_FAILED;
145 break;
146 }
147
148 if (ctx)
149 krb5_init_creds_free(context, ctx);
150
151 krb5_free_context(context);
152 return ret;
153 }
154 #endif /* WITH_GSSAPI */
155
transport_ssl_cb(SSL * ssl,int where,int ret)156 static void transport_ssl_cb(SSL* ssl, int where, int ret)
157 {
158 if (where & SSL_CB_ALERT)
159 {
160 rdpTransport* transport = (rdpTransport*)SSL_get_app_data(ssl);
161
162 switch (ret)
163 {
164 case (SSL3_AL_FATAL << 8) | SSL_AD_ACCESS_DENIED:
165 {
166 if (!freerdp_get_last_error(transport->context))
167 {
168 WLog_Print(transport->log, WLOG_ERROR, "%s: ACCESS DENIED", __FUNCTION__);
169 freerdp_set_last_error_log(transport->context,
170 FREERDP_ERROR_AUTHENTICATION_FAILED);
171 }
172 }
173 break;
174
175 case (SSL3_AL_FATAL << 8) | SSL_AD_INTERNAL_ERROR:
176 {
177 if (transport->NlaMode)
178 {
179 UINT32 kret = 0;
180 #ifdef WITH_GSSAPI
181
182 if ((strlen(transport->settings->Domain) != 0) &&
183 (strncmp(transport->settings->Domain, ".", 1) != 0))
184 {
185 kret = transport_krb5_check_account(
186 transport, transport->settings->Username, transport->settings->Domain,
187 transport->settings->Password);
188 }
189 else
190 #endif /* WITH_GSSAPI */
191 kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
192
193 freerdp_set_last_error_if_not(transport->context, kret);
194 }
195
196 break;
197
198 case (SSL3_AL_WARNING << 8) | SSL3_AD_CLOSE_NOTIFY:
199 break;
200
201 default:
202 WLog_Print(transport->log, WLOG_WARN,
203 "Unhandled SSL error (where=%d, ret=%d [%s, %s])", where, ret,
204 SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret));
205 break;
206 }
207 }
208 }
209 }
210
transport_send_stream_init(rdpTransport * transport,int size)211 wStream* transport_send_stream_init(rdpTransport* transport, int size)
212 {
213 wStream* s;
214
215 if (!(s = StreamPool_Take(transport->ReceivePool, size)))
216 return NULL;
217
218 if (!Stream_EnsureCapacity(s, size))
219 {
220 Stream_Release(s);
221 return NULL;
222 }
223
224 Stream_SetPosition(s, 0);
225 return s;
226 }
227
transport_attach(rdpTransport * transport,int sockfd)228 BOOL transport_attach(rdpTransport* transport, int sockfd)
229 {
230 BIO* socketBio = NULL;
231 BIO* bufferedBio;
232 socketBio = BIO_new(BIO_s_simple_socket());
233
234 if (!socketBio)
235 goto fail;
236
237 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
238 bufferedBio = BIO_new(BIO_s_buffered_socket());
239
240 if (!bufferedBio)
241 goto fail;
242
243 bufferedBio = BIO_push(bufferedBio, socketBio);
244 transport->frontBio = bufferedBio;
245 return TRUE;
246 fail:
247
248 if (socketBio)
249 BIO_free_all(socketBio);
250 else
251 close(sockfd);
252
253 return FALSE;
254 }
255
transport_connect_rdp(rdpTransport * transport)256 BOOL transport_connect_rdp(rdpTransport* transport)
257 {
258 /* RDP encryption */
259 return TRUE;
260 }
261
transport_connect_tls(rdpTransport * transport)262 BOOL transport_connect_tls(rdpTransport* transport)
263 {
264 int tlsStatus;
265 rdpTls* tls = NULL;
266 rdpContext* context = transport->context;
267 rdpSettings* settings = transport->settings;
268
269 if (!(tls = tls_new(settings)))
270 return FALSE;
271
272 transport->tls = tls;
273
274 if (transport->GatewayEnabled)
275 transport->layer = TRANSPORT_LAYER_TSG_TLS;
276 else
277 transport->layer = TRANSPORT_LAYER_TLS;
278
279 tls->hostname = settings->ServerHostname;
280 tls->port = settings->ServerPort;
281
282 if (tls->port == 0)
283 tls->port = 3389;
284
285 tls->isGatewayTransport = FALSE;
286 tlsStatus = tls_connect(tls, transport->frontBio);
287
288 if (tlsStatus < 1)
289 {
290 if (tlsStatus < 0)
291 {
292 freerdp_set_last_error_if_not(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
293 }
294 else
295 {
296 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
297 }
298
299 return FALSE;
300 }
301
302 transport->frontBio = tls->bio;
303 BIO_callback_ctrl(tls->bio, BIO_CTRL_SET_CALLBACK, (bio_info_cb*)(void*)transport_ssl_cb);
304 SSL_set_app_data(tls->ssl, transport);
305
306 if (!transport->frontBio)
307 {
308 WLog_Print(transport->log, WLOG_ERROR, "unable to prepend a filtering TLS bio");
309 return FALSE;
310 }
311
312 return TRUE;
313 }
314
transport_connect_nla(rdpTransport * transport)315 BOOL transport_connect_nla(rdpTransport* transport)
316 {
317 rdpContext* context = transport->context;
318 rdpSettings* settings = context->settings;
319 freerdp* instance = context->instance;
320 rdpRdp* rdp = context->rdp;
321
322 if (!transport_connect_tls(transport))
323 return FALSE;
324
325 if (!settings->Authentication)
326 return TRUE;
327
328 nla_free(rdp->nla);
329 rdp->nla = nla_new(instance, transport, settings);
330
331 if (!rdp->nla)
332 return FALSE;
333
334 transport_set_nla_mode(transport, TRUE);
335
336 if (settings->AuthenticationServiceClass)
337 {
338 if (!nla_set_service_principal(rdp->nla, nla_make_spn(settings->AuthenticationServiceClass,
339 settings->ServerHostname)))
340 return FALSE;
341 }
342
343 if (nla_client_begin(rdp->nla) < 0)
344 {
345 WLog_Print(transport->log, WLOG_ERROR, "NLA begin failed");
346
347 freerdp_set_last_error_if_not(context, FREERDP_ERROR_AUTHENTICATION_FAILED);
348
349 transport_set_nla_mode(transport, FALSE);
350 return FALSE;
351 }
352
353 rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA);
354 return TRUE;
355 }
356
transport_connect(rdpTransport * transport,const char * hostname,UINT16 port,DWORD timeout)357 BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port, DWORD timeout)
358 {
359 int sockfd;
360 BOOL status = FALSE;
361 rdpSettings* settings = transport->settings;
362 rdpContext* context = transport->context;
363 BOOL rpcFallback = !settings->GatewayHttpTransport;
364
365 if (transport->GatewayEnabled)
366 {
367 if (!status && settings->GatewayHttpTransport)
368 {
369 transport->rdg = rdg_new(context);
370
371 if (!transport->rdg)
372 return FALSE;
373
374 status = rdg_connect(transport->rdg, timeout, &rpcFallback);
375
376 if (status)
377 {
378 transport->frontBio = rdg_get_front_bio_and_take_ownership(transport->rdg);
379 BIO_set_nonblock(transport->frontBio, 0);
380 transport->layer = TRANSPORT_LAYER_TSG;
381 status = TRUE;
382 }
383 else
384 {
385 rdg_free(transport->rdg);
386 transport->rdg = NULL;
387 }
388 }
389
390 if (!status && settings->GatewayRpcTransport && rpcFallback)
391 {
392 transport->tsg = tsg_new(transport);
393
394 if (!transport->tsg)
395 return FALSE;
396
397 /* Reset error condition from RDG */
398 freerdp_set_last_error_log(context, FREERDP_ERROR_SUCCESS);
399 status = tsg_connect(transport->tsg, hostname, port, timeout);
400
401 if (status)
402 {
403 transport->frontBio = tsg_get_bio(transport->tsg);
404 transport->layer = TRANSPORT_LAYER_TSG;
405 status = TRUE;
406 }
407 else
408 {
409 tsg_free(transport->tsg);
410 transport->tsg = NULL;
411 }
412 }
413 }
414 else
415 {
416 UINT16 peerPort;
417 const char *proxyHostname, *proxyUsername, *proxyPassword;
418 BOOL isProxyConnection =
419 proxy_prepare(settings, &proxyHostname, &peerPort, &proxyUsername, &proxyPassword);
420
421 if (isProxyConnection)
422 sockfd = freerdp_tcp_connect(context, settings, proxyHostname, peerPort, timeout);
423 else
424 sockfd = freerdp_tcp_connect(context, settings, hostname, port, timeout);
425
426 if (sockfd < 0)
427 return FALSE;
428
429 if (!transport_attach(transport, sockfd))
430 return FALSE;
431
432 if (isProxyConnection)
433 {
434 if (!proxy_connect(settings, transport->frontBio, proxyUsername, proxyPassword,
435 hostname, port))
436 return FALSE;
437 }
438
439 status = TRUE;
440 }
441
442 return status;
443 }
444
transport_accept_rdp(rdpTransport * transport)445 BOOL transport_accept_rdp(rdpTransport* transport)
446 {
447 /* RDP encryption */
448 return TRUE;
449 }
450
transport_accept_tls(rdpTransport * transport)451 BOOL transport_accept_tls(rdpTransport* transport)
452 {
453 rdpSettings* settings = transport->settings;
454
455 if (!transport->tls)
456 transport->tls = tls_new(transport->settings);
457
458 transport->layer = TRANSPORT_LAYER_TLS;
459
460 if (!tls_accept(transport->tls, transport->frontBio, settings))
461 return FALSE;
462
463 transport->frontBio = transport->tls->bio;
464 return TRUE;
465 }
466
transport_accept_nla(rdpTransport * transport)467 BOOL transport_accept_nla(rdpTransport* transport)
468 {
469 rdpSettings* settings = transport->settings;
470 freerdp* instance = (freerdp*)settings->instance;
471
472 if (!transport->tls)
473 transport->tls = tls_new(transport->settings);
474
475 transport->layer = TRANSPORT_LAYER_TLS;
476
477 if (!tls_accept(transport->tls, transport->frontBio, settings))
478 return FALSE;
479
480 transport->frontBio = transport->tls->bio;
481
482 /* Network Level Authentication */
483
484 if (!settings->Authentication)
485 return TRUE;
486
487 if (!transport->nla)
488 {
489 transport->nla = nla_new(instance, transport, settings);
490 transport_set_nla_mode(transport, TRUE);
491 }
492
493 if (nla_authenticate(transport->nla) < 0)
494 {
495 WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
496 transport_set_nla_mode(transport, FALSE);
497 nla_free(transport->nla);
498 transport->nla = NULL;
499 tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
500 TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
501 tls_send_alert(transport->tls);
502 return FALSE;
503 }
504
505 /* don't free nla module yet, we need to copy the credentials from it first */
506 transport_set_nla_mode(transport, FALSE);
507 return TRUE;
508 }
509
510 #define WLog_ERR_BIO(transport, biofunc, bio) \
511 transport_bio_error_log(transport, biofunc, bio, __FILE__, __FUNCTION__, __LINE__)
512
transport_bio_error_log(rdpTransport * transport,LPCSTR biofunc,BIO * bio,LPCSTR file,LPCSTR func,DWORD line)513 static void transport_bio_error_log(rdpTransport* transport, LPCSTR biofunc, BIO* bio, LPCSTR file,
514 LPCSTR func, DWORD line)
515 {
516 unsigned long sslerr;
517 char* buf;
518 int saveerrno;
519 DWORD level;
520 saveerrno = errno;
521 level = WLOG_ERROR;
522
523 if (level < WLog_GetLogLevel(transport->log))
524 return;
525
526 if (ERR_peek_error() == 0)
527 {
528 const char* fmt = "%s returned a system error %d: %s";
529 WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt, biofunc,
530 saveerrno, strerror(saveerrno));
531 return;
532 }
533
534 buf = malloc(120);
535
536 if (buf)
537 {
538 const char* fmt = "%s returned an error: %s";
539
540 while ((sslerr = ERR_get_error()))
541 {
542 ERR_error_string_n(sslerr, buf, 120);
543 WLog_PrintMessage(transport->log, WLOG_MESSAGE_TEXT, level, line, file, func, fmt,
544 biofunc, buf);
545 }
546
547 free(buf);
548 }
549 }
550
transport_read_layer(rdpTransport * transport,BYTE * data,size_t bytes)551 static SSIZE_T transport_read_layer(rdpTransport* transport, BYTE* data, size_t bytes)
552 {
553 SSIZE_T read = 0;
554 rdpRdp* rdp = transport->context->rdp;
555
556 if (!transport->frontBio || (bytes > SSIZE_MAX))
557 {
558 transport->layer = TRANSPORT_LAYER_CLOSED;
559 freerdp_set_last_error_if_not(transport->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
560 return -1;
561 }
562
563 while (read < (SSIZE_T)bytes)
564 {
565 const SSIZE_T tr = (SSIZE_T)bytes - read;
566 int r = (int)((tr > INT_MAX) ? INT_MAX : tr);
567 int status = BIO_read(transport->frontBio, data + read, r);
568
569 if (status <= 0)
570 {
571 if (!transport->frontBio || !BIO_should_retry(transport->frontBio))
572 {
573 /* something unexpected happened, let's close */
574 if (!transport->frontBio)
575 {
576 WLog_Print(transport->log, WLOG_ERROR, "BIO_read: transport->frontBio null");
577 return -1;
578 }
579
580 WLog_ERR_BIO(transport, "BIO_read", transport->frontBio);
581 transport->layer = TRANSPORT_LAYER_CLOSED;
582 freerdp_set_last_error_if_not(transport->context,
583 FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
584 return -1;
585 }
586
587 /* non blocking will survive a partial read */
588 if (!transport->blocking)
589 return read;
590
591 /* blocking means that we can't continue until we have read the number of requested
592 * bytes */
593 if (BIO_wait_read(transport->frontBio, 100) < 0)
594 {
595 WLog_ERR_BIO(transport, "BIO_wait_read", transport->frontBio);
596 return -1;
597 }
598
599 continue;
600 }
601
602 #ifdef HAVE_VALGRIND_MEMCHECK_H
603 VALGRIND_MAKE_MEM_DEFINED(data + read, bytes - read);
604 #endif
605 read += status;
606 rdp->inBytes += status;
607 }
608
609 return read;
610 }
611
612 /**
613 * @brief Tries to read toRead bytes from the specified transport
614 *
615 * Try to read toRead bytes from the transport to the stream.
616 * In case it was not possible to read toRead bytes 0 is returned. The stream is always advanced by
617 * the number of bytes read.
618 *
619 * The function assumes that the stream has enough capacity to hold the data.
620 *
621 * @param[in] transport rdpTransport
622 * @param[in] s wStream
623 * @param[in] toRead number of bytes to read
624 * @return < 0 on error; 0 if not enough data is available (non blocking mode); 1 toRead bytes read
625 */
transport_read_layer_bytes(rdpTransport * transport,wStream * s,size_t toRead)626 static SSIZE_T transport_read_layer_bytes(rdpTransport* transport, wStream* s, size_t toRead)
627 {
628 SSIZE_T status;
629 if (toRead > SSIZE_MAX)
630 return 0;
631
632 status = transport_read_layer(transport, Stream_Pointer(s), toRead);
633
634 if (status <= 0)
635 return status;
636
637 Stream_Seek(s, (size_t)status);
638 return status == (SSIZE_T)toRead ? 1 : 0;
639 }
640
641 /**
642 * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport.
643 *
644 * If possible a complete PDU is read, in case of non blocking transport this might not succeed.
645 * Except in case of an error the passed stream will point to the last byte read (correct
646 * position). When the pdu read is completed the stream is sealed and the pointer set to 0
647 *
648 * @param[in] transport rdpTransport
649 * @param[in] s wStream
650 * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of
651 * bytes of the *complete* pdu read
652 */
transport_read_pdu(rdpTransport * transport,wStream * s)653 int transport_read_pdu(rdpTransport* transport, wStream* s)
654 {
655 int status;
656 size_t position;
657 size_t pduLength;
658 BYTE* header;
659 pduLength = 0;
660
661 if (!transport)
662 return -1;
663
664 if (!s)
665 return -1;
666
667 position = Stream_GetPosition(s);
668
669 /* Make sure there is enough space for the longest header within the stream */
670 if (!Stream_EnsureCapacity(s, 4))
671 return -1;
672
673 /* Make sure at least two bytes are read for further processing */
674 if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1)
675 {
676 /* No data available at the moment */
677 return status;
678 }
679
680 /* update position value for further checks */
681 position = Stream_GetPosition(s);
682 header = Stream_Buffer(s);
683
684 if (transport->NlaMode)
685 {
686 /*
687 * In case NlaMode is set TSRequest package(s) are expected
688 * 0x30 = DER encoded data with these bits set:
689 * bit 6 P/C constructed
690 * bit 5 tag number - sequence
691 */
692 if (header[0] == 0x30)
693 {
694 /* TSRequest (NLA) */
695 if (header[1] & 0x80)
696 {
697 if ((header[1] & ~(0x80)) == 1)
698 {
699 /* check for header bytes already was readed in previous calls */
700 if (position < 3 &&
701 (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
702 return status;
703
704 pduLength = header[2];
705 pduLength += 3;
706 }
707 else if ((header[1] & ~(0x80)) == 2)
708 {
709 /* check for header bytes already was readed in previous calls */
710 if (position < 4 &&
711 (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
712 return status;
713
714 pduLength = (header[2] << 8) | header[3];
715 pduLength += 4;
716 }
717 else
718 {
719 WLog_Print(transport->log, WLOG_ERROR, "Error reading TSRequest!");
720 return -1;
721 }
722 }
723 else
724 {
725 pduLength = header[1];
726 pduLength += 2;
727 }
728 }
729 }
730 else
731 {
732 if (header[0] == 0x03)
733 {
734 /* TPKT header */
735 /* check for header bytes already was readed in previous calls */
736 if (position < 4 &&
737 (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1)
738 return status;
739
740 pduLength = (header[2] << 8) | header[3];
741
742 /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */
743 if (pduLength < 7 || pduLength > 0xFFFF)
744 {
745 WLog_Print(transport->log, WLOG_ERROR, "tpkt - invalid pduLength: %" PRIdz,
746 pduLength);
747 return -1;
748 }
749 }
750 else
751 {
752 /* Fast-Path Header */
753 if (header[1] & 0x80)
754 {
755 /* check for header bytes already was readed in previous calls */
756 if (position < 3 &&
757 (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1)
758 return status;
759
760 pduLength = ((header[1] & 0x7F) << 8) | header[2];
761 }
762 else
763 pduLength = header[1];
764
765 /*
766 * fast-path has 7 bits for length so the maximum size, including headers is 0x8000
767 * The theoretical minimum fast-path PDU consists only of two header bytes plus one
768 * byte for data (e.g. fast-path input synchronize pdu)
769 */
770 if (pduLength < 3 || pduLength > 0x8000)
771 {
772 WLog_Print(transport->log, WLOG_ERROR, "fast path - invalid pduLength: %" PRIdz,
773 pduLength);
774 return -1;
775 }
776 }
777 }
778
779 if (!Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength))
780 return -1;
781
782 status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s));
783
784 if (status != 1)
785 return status;
786
787 if (Stream_GetPosition(s) >= pduLength)
788 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND);
789
790 Stream_SealLength(s);
791 Stream_SetPosition(s, 0);
792 return Stream_Length(s);
793 }
794
transport_write(rdpTransport * transport,wStream * s)795 int transport_write(rdpTransport* transport, wStream* s)
796 {
797 size_t length;
798 int status = -1;
799 int writtenlength = 0;
800 rdpRdp* rdp = transport->context->rdp;
801
802 if (!s)
803 return -1;
804
805 if (!transport)
806 goto fail;
807
808 if (!transport->frontBio)
809 {
810 transport->layer = TRANSPORT_LAYER_CLOSED;
811 freerdp_set_last_error_if_not(transport->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
812 goto fail;
813 }
814
815 EnterCriticalSection(&(transport->WriteLock));
816 length = Stream_GetPosition(s);
817 writtenlength = length;
818 Stream_SetPosition(s, 0);
819
820 if (length > 0)
821 {
822 rdp->outBytes += length;
823 WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), length, WLOG_PACKET_OUTBOUND);
824 }
825
826 while (length > 0)
827 {
828 status = BIO_write(transport->frontBio, Stream_Pointer(s), length);
829
830 if (status <= 0)
831 {
832 /* the buffered BIO that is at the end of the chain always says OK for writing,
833 * so a retry means that for any reason we need to read. The most probable
834 * is a SSL or TSG BIO in the chain.
835 */
836 if (!BIO_should_retry(transport->frontBio))
837 {
838 WLog_ERR_BIO(transport, "BIO_should_retry", transport->frontBio);
839 goto out_cleanup;
840 }
841
842 /* non-blocking can live with blocked IOs */
843 if (!transport->blocking)
844 {
845 WLog_ERR_BIO(transport, "BIO_write", transport->frontBio);
846 goto out_cleanup;
847 }
848
849 if (BIO_wait_write(transport->frontBio, 100) < 0)
850 {
851 WLog_ERR_BIO(transport, "BIO_wait_write", transport->frontBio);
852 status = -1;
853 goto out_cleanup;
854 }
855
856 continue;
857 }
858
859 if (transport->blocking || transport->settings->WaitForOutputBufferFlush)
860 {
861 while (BIO_write_blocked(transport->frontBio))
862 {
863 if (BIO_wait_write(transport->frontBio, 100) < 0)
864 {
865 WLog_Print(transport->log, WLOG_ERROR, "error when selecting for write");
866 status = -1;
867 goto out_cleanup;
868 }
869
870 if (BIO_flush(transport->frontBio) < 1)
871 {
872 WLog_Print(transport->log, WLOG_ERROR, "error when flushing outputBuffer");
873 status = -1;
874 goto out_cleanup;
875 }
876 }
877 }
878
879 length -= status;
880 Stream_Seek(s, status);
881 }
882
883 transport->written += writtenlength;
884 out_cleanup:
885
886 if (status < 0)
887 {
888 /* A write error indicates that the peer has dropped the connection */
889 transport->layer = TRANSPORT_LAYER_CLOSED;
890 freerdp_set_last_error_if_not(transport->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
891 }
892
893 LeaveCriticalSection(&(transport->WriteLock));
894 fail:
895 Stream_Release(s);
896 return status;
897 }
898
transport_get_event_handles(rdpTransport * transport,HANDLE * events,DWORD count)899 DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count)
900 {
901 DWORD nCount = 1; /* always the reread Event */
902 DWORD tmp;
903
904 if (events)
905 {
906 if (count < 1)
907 {
908 WLog_Print(transport->log, WLOG_ERROR, "%s: provided handles array is too small",
909 __FUNCTION__);
910 return 0;
911 }
912
913 events[0] = transport->rereadEvent;
914 }
915
916 if (!transport->GatewayEnabled)
917 {
918 nCount++;
919
920 if (events)
921 {
922 if (nCount > count)
923 {
924 WLog_Print(transport->log, WLOG_ERROR,
925 "%s: provided handles array is too small (count=%" PRIu32
926 " nCount=%" PRIu32 ")",
927 __FUNCTION__, count, nCount);
928 return 0;
929 }
930
931 if (BIO_get_event(transport->frontBio, &events[1]) != 1)
932 {
933 WLog_Print(transport->log, WLOG_ERROR, "%s: error getting the frontBio handle",
934 __FUNCTION__);
935 return 0;
936 }
937 }
938 }
939 else
940 {
941 if (transport->rdg)
942 {
943 tmp = rdg_get_event_handles(transport->rdg, &events[1], count - 1);
944
945 if (tmp == 0)
946 return 0;
947
948 nCount += tmp;
949 }
950 else if (transport->tsg)
951 {
952 tmp = tsg_get_event_handles(transport->tsg, &events[1], count - 1);
953
954 if (tmp == 0)
955 return 0;
956
957 nCount += tmp;
958 }
959 }
960
961 return nCount;
962 }
963
transport_get_fds(rdpTransport * transport,void ** rfds,int * rcount)964 void transport_get_fds(rdpTransport* transport, void** rfds, int* rcount)
965 {
966 DWORD index;
967 DWORD nCount;
968 HANDLE events[64];
969 nCount = transport_get_event_handles(transport, events, 64);
970 *rcount = nCount + 1;
971
972 for (index = 0; index < nCount; index++)
973 {
974 rfds[index] = GetEventWaitObject(events[index]);
975 }
976
977 rfds[nCount] = GetEventWaitObject(transport->rereadEvent);
978 }
979
transport_is_write_blocked(rdpTransport * transport)980 BOOL transport_is_write_blocked(rdpTransport* transport)
981 {
982 return BIO_write_blocked(transport->frontBio);
983 }
984
transport_drain_output_buffer(rdpTransport * transport)985 int transport_drain_output_buffer(rdpTransport* transport)
986 {
987 BOOL status = FALSE;
988
989 if (BIO_write_blocked(transport->frontBio))
990 {
991 if (BIO_flush(transport->frontBio) < 1)
992 return -1;
993
994 status |= BIO_write_blocked(transport->frontBio);
995 }
996
997 return status;
998 }
999
transport_check_fds(rdpTransport * transport)1000 int transport_check_fds(rdpTransport* transport)
1001 {
1002 int status;
1003 int recv_status;
1004 wStream* received;
1005 UINT64 now = GetTickCount64();
1006 UINT64 dueDate = 0;
1007
1008 if (!transport)
1009 return -1;
1010
1011 if (transport->layer == TRANSPORT_LAYER_CLOSED)
1012 {
1013 WLog_Print(transport->log, WLOG_DEBUG, "transport_check_fds: transport layer closed");
1014 freerdp_set_last_error_if_not(transport->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED);
1015 return -1;
1016 }
1017
1018 dueDate = now + transport->settings->MaxTimeInCheckLoop;
1019
1020 if (transport->haveMoreBytesToRead)
1021 {
1022 transport->haveMoreBytesToRead = FALSE;
1023 ResetEvent(transport->rereadEvent);
1024 }
1025
1026 while (now < dueDate)
1027 {
1028 if (freerdp_shall_disconnect(transport->context->instance))
1029 {
1030 return -1;
1031 }
1032
1033 /**
1034 * Note: transport_read_pdu tries to read one PDU from
1035 * the transport layer.
1036 * The ReceiveBuffer might have a position > 0 in case of a non blocking
1037 * transport. If transport_read_pdu returns 0 the pdu couldn't be read at
1038 * this point.
1039 * Note that transport->ReceiveBuffer is replaced after each iteration
1040 * of this loop with a fresh stream instance from a pool.
1041 */
1042 if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
1043 {
1044 if (status < 0)
1045 WLog_Print(transport->log, WLOG_DEBUG,
1046 "transport_check_fds: transport_read_pdu() - %i", status);
1047
1048 return status;
1049 }
1050
1051 received = transport->ReceiveBuffer;
1052
1053 if (!(transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0)))
1054 return -1;
1055
1056 /**
1057 * status:
1058 * -1: error
1059 * 0: success
1060 * 1: redirection
1061 */
1062 recv_status = transport->ReceiveCallback(transport, received, transport->ReceiveExtra);
1063 Stream_Release(received);
1064
1065 /* session redirection or activation */
1066 if (recv_status == 1 || recv_status == 2)
1067 {
1068 return recv_status;
1069 }
1070
1071 if (recv_status < 0)
1072 {
1073 WLog_Print(transport->log, WLOG_ERROR,
1074 "transport_check_fds: transport->ReceiveCallback() - %i", recv_status);
1075 return -1;
1076 }
1077
1078 now = GetTickCount64();
1079 }
1080
1081 if (now >= dueDate)
1082 {
1083 SetEvent(transport->rereadEvent);
1084 transport->haveMoreBytesToRead = TRUE;
1085 }
1086
1087 return 0;
1088 }
1089
transport_set_blocking_mode(rdpTransport * transport,BOOL blocking)1090 BOOL transport_set_blocking_mode(rdpTransport* transport, BOOL blocking)
1091 {
1092 transport->blocking = blocking;
1093
1094 if (!BIO_set_nonblock(transport->frontBio, blocking ? FALSE : TRUE))
1095 return FALSE;
1096
1097 return TRUE;
1098 }
1099
transport_set_gateway_enabled(rdpTransport * transport,BOOL GatewayEnabled)1100 void transport_set_gateway_enabled(rdpTransport* transport, BOOL GatewayEnabled)
1101 {
1102 transport->GatewayEnabled = GatewayEnabled;
1103 }
1104
transport_set_nla_mode(rdpTransport * transport,BOOL NlaMode)1105 void transport_set_nla_mode(rdpTransport* transport, BOOL NlaMode)
1106 {
1107 transport->NlaMode = NlaMode;
1108 }
1109
transport_disconnect(rdpTransport * transport)1110 BOOL transport_disconnect(rdpTransport* transport)
1111 {
1112 BOOL status = TRUE;
1113
1114 if (!transport)
1115 return FALSE;
1116
1117 if (transport->tls)
1118 {
1119 tls_free(transport->tls);
1120 transport->tls = NULL;
1121 }
1122 else
1123 {
1124 if (transport->frontBio)
1125 BIO_free_all(transport->frontBio);
1126 }
1127
1128 if (transport->tsg)
1129 {
1130 tsg_free(transport->tsg);
1131 transport->tsg = NULL;
1132 }
1133
1134 if (transport->rdg)
1135 {
1136 rdg_free(transport->rdg);
1137 transport->rdg = NULL;
1138 }
1139
1140 transport->frontBio = NULL;
1141 transport->layer = TRANSPORT_LAYER_TCP;
1142 return status;
1143 }
1144
transport_new(rdpContext * context)1145 rdpTransport* transport_new(rdpContext* context)
1146 {
1147 rdpTransport* transport;
1148 transport = (rdpTransport*)calloc(1, sizeof(rdpTransport));
1149
1150 if (!transport)
1151 return NULL;
1152
1153 transport->log = WLog_Get(TAG);
1154
1155 if (!transport->log)
1156 goto out_free_transport;
1157
1158 transport->context = context;
1159 transport->settings = context->settings;
1160 transport->ReceivePool = StreamPool_New(TRUE, BUFFER_SIZE);
1161
1162 if (!transport->ReceivePool)
1163 goto out_free_transport;
1164
1165 /* receive buffer for non-blocking read. */
1166 transport->ReceiveBuffer = StreamPool_Take(transport->ReceivePool, 0);
1167
1168 if (!transport->ReceiveBuffer)
1169 goto out_free_receivepool;
1170
1171 transport->connectedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1172
1173 if (!transport->connectedEvent || transport->connectedEvent == INVALID_HANDLE_VALUE)
1174 goto out_free_receivebuffer;
1175
1176 transport->rereadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1177
1178 if (!transport->rereadEvent || transport->rereadEvent == INVALID_HANDLE_VALUE)
1179 goto out_free_connectedEvent;
1180
1181 transport->haveMoreBytesToRead = FALSE;
1182 transport->blocking = TRUE;
1183 transport->GatewayEnabled = FALSE;
1184 transport->layer = TRANSPORT_LAYER_TCP;
1185
1186 if (!InitializeCriticalSectionAndSpinCount(&(transport->ReadLock), 4000))
1187 goto out_free_rereadEvent;
1188
1189 if (!InitializeCriticalSectionAndSpinCount(&(transport->WriteLock), 4000))
1190 goto out_free_readlock;
1191
1192 return transport;
1193 out_free_readlock:
1194 DeleteCriticalSection(&(transport->ReadLock));
1195 out_free_rereadEvent:
1196 CloseHandle(transport->rereadEvent);
1197 out_free_connectedEvent:
1198 CloseHandle(transport->connectedEvent);
1199 out_free_receivebuffer:
1200 StreamPool_Return(transport->ReceivePool, transport->ReceiveBuffer);
1201 out_free_receivepool:
1202 StreamPool_Free(transport->ReceivePool);
1203 out_free_transport:
1204 free(transport);
1205 return NULL;
1206 }
1207
transport_free(rdpTransport * transport)1208 void transport_free(rdpTransport* transport)
1209 {
1210 if (!transport)
1211 return;
1212
1213 transport_disconnect(transport);
1214
1215 if (transport->ReceiveBuffer)
1216 Stream_Release(transport->ReceiveBuffer);
1217
1218 nla_free(transport->nla);
1219 StreamPool_Free(transport->ReceivePool);
1220 CloseHandle(transport->connectedEvent);
1221 CloseHandle(transport->rereadEvent);
1222 DeleteCriticalSection(&(transport->ReadLock));
1223 DeleteCriticalSection(&(transport->WriteLock));
1224 free(transport);
1225 }
1226