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