1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * RDP Protocol Security Negotiation
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
7  * Copyright 2015 Thincast Technologies GmbH
8  * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <winpr/crt.h>
28 
29 #include <freerdp/log.h>
30 
31 #include "tpkt.h"
32 
33 #include "nego.h"
34 
35 #include "transport.h"
36 
37 #define TAG FREERDP_TAG("core.nego")
38 
39 struct rdp_nego
40 {
41 	UINT16 port;
42 	UINT32 flags;
43 	const char* hostname;
44 	char* cookie;
45 	BYTE* RoutingToken;
46 	DWORD RoutingTokenLength;
47 	BOOL SendPreconnectionPdu;
48 	UINT32 PreconnectionId;
49 	char* PreconnectionBlob;
50 
51 	NEGO_STATE state;
52 	BOOL TcpConnected;
53 	BOOL SecurityConnected;
54 	UINT32 CookieMaxLength;
55 
56 	BOOL sendNegoData;
57 	UINT32 SelectedProtocol;
58 	UINT32 RequestedProtocols;
59 	BOOL NegotiateSecurityLayer;
60 	BOOL EnabledProtocols[16];
61 	BOOL RestrictedAdminModeRequired;
62 	BOOL GatewayEnabled;
63 	BOOL GatewayBypassLocal;
64 
65 	rdpTransport* transport;
66 };
67 
nego_state_string(NEGO_STATE state)68 static const char* nego_state_string(NEGO_STATE state)
69 {
70 	static const char* const NEGO_STATE_STRINGS[] = { "NEGO_STATE_INITIAL", "NEGO_STATE_EXT",
71 		                                              "NEGO_STATE_NLA",     "NEGO_STATE_TLS",
72 		                                              "NEGO_STATE_RDP",     "NEGO_STATE_FAIL",
73 		                                              "NEGO_STATE_FINAL",   "NEGO_STATE_INVALID" };
74 	if (state >= ARRAYSIZE(NEGO_STATE_STRINGS))
75 		return NEGO_STATE_STRINGS[ARRAYSIZE(NEGO_STATE_STRINGS) - 1];
76 	return NEGO_STATE_STRINGS[state];
77 }
78 
protocol_security_string(UINT32 security)79 static const char* protocol_security_string(UINT32 security)
80 {
81 	static const char* PROTOCOL_SECURITY_STRINGS[] = { "RDP", "TLS", "NLA", "UNK", "UNK",
82 		                                               "UNK", "UNK", "UNK", "EXT", "UNK" };
83 	if (security >= ARRAYSIZE(PROTOCOL_SECURITY_STRINGS))
84 		return PROTOCOL_SECURITY_STRINGS[ARRAYSIZE(PROTOCOL_SECURITY_STRINGS) - 1];
85 	return PROTOCOL_SECURITY_STRINGS[security];
86 }
87 
88 static BOOL nego_transport_connect(rdpNego* nego);
89 static BOOL nego_transport_disconnect(rdpNego* nego);
90 static BOOL nego_security_connect(rdpNego* nego);
91 static BOOL nego_send_preconnection_pdu(rdpNego* nego);
92 static BOOL nego_recv_response(rdpNego* nego);
93 static void nego_send(rdpNego* nego);
94 static BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s);
95 static BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s);
96 static BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s);
97 
98 /**
99  * Negotiate protocol security and connect.
100  * @param nego
101  * @return
102  */
103 
nego_connect(rdpNego * nego)104 BOOL nego_connect(rdpNego* nego)
105 {
106 	rdpSettings* settings = nego->transport->settings;
107 
108 	if (nego->state == NEGO_STATE_INITIAL)
109 	{
110 		if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
111 		{
112 			nego->state = NEGO_STATE_EXT;
113 		}
114 		else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
115 		{
116 			nego->state = NEGO_STATE_NLA;
117 		}
118 		else if (nego->EnabledProtocols[PROTOCOL_SSL])
119 		{
120 			nego->state = NEGO_STATE_TLS;
121 		}
122 		else if (nego->EnabledProtocols[PROTOCOL_RDP])
123 		{
124 			nego->state = NEGO_STATE_RDP;
125 		}
126 		else
127 		{
128 			WLog_ERR(TAG, "No security protocol is enabled");
129 			nego->state = NEGO_STATE_FAIL;
130 			return FALSE;
131 		}
132 
133 		if (!nego->NegotiateSecurityLayer)
134 		{
135 			WLog_DBG(TAG, "Security Layer Negotiation is disabled");
136 			/* attempt only the highest enabled protocol (see nego_attempt_*) */
137 			nego->EnabledProtocols[PROTOCOL_HYBRID] = FALSE;
138 			nego->EnabledProtocols[PROTOCOL_SSL] = FALSE;
139 			nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
140 			nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = FALSE;
141 
142 			if (nego->state == NEGO_STATE_EXT)
143 			{
144 				nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
145 				nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
146 				nego->SelectedProtocol = PROTOCOL_HYBRID_EX;
147 			}
148 			else if (nego->state == NEGO_STATE_NLA)
149 			{
150 				nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
151 				nego->SelectedProtocol = PROTOCOL_HYBRID;
152 			}
153 			else if (nego->state == NEGO_STATE_TLS)
154 			{
155 				nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
156 				nego->SelectedProtocol = PROTOCOL_SSL;
157 			}
158 			else if (nego->state == NEGO_STATE_RDP)
159 			{
160 				nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
161 				nego->SelectedProtocol = PROTOCOL_RDP;
162 			}
163 		}
164 
165 		if (nego->SendPreconnectionPdu)
166 		{
167 			if (!nego_send_preconnection_pdu(nego))
168 			{
169 				WLog_ERR(TAG, "Failed to send preconnection pdu");
170 				nego->state = NEGO_STATE_FINAL;
171 				return FALSE;
172 			}
173 		}
174 	}
175 
176 	if (!nego->NegotiateSecurityLayer)
177 	{
178 		nego->state = NEGO_STATE_FINAL;
179 	}
180 	else
181 	{
182 		do
183 		{
184 			WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
185 			nego_send(nego);
186 
187 			if (nego->state == NEGO_STATE_FAIL)
188 			{
189 				if (freerdp_get_last_error(nego->transport->context) == FREERDP_ERROR_SUCCESS)
190 					WLog_ERR(TAG, "Protocol Security Negotiation Failure");
191 
192 				nego->state = NEGO_STATE_FINAL;
193 				return FALSE;
194 			}
195 		} while (nego->state != NEGO_STATE_FINAL);
196 	}
197 
198 	WLog_DBG(TAG, "Negotiated %s security", protocol_security_string(nego->SelectedProtocol));
199 	/* update settings with negotiated protocol security */
200 	settings->RequestedProtocols = nego->RequestedProtocols;
201 	settings->SelectedProtocol = nego->SelectedProtocol;
202 	settings->NegotiationFlags = nego->flags;
203 
204 	if (nego->SelectedProtocol == PROTOCOL_RDP)
205 	{
206 		settings->UseRdpSecurityLayer = TRUE;
207 
208 		if (!settings->EncryptionMethods)
209 		{
210 			/**
211 			 * Advertise all supported encryption methods if the client
212 			 * implementation did not set any security methods
213 			 */
214 			settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
215 			                              ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
216 		}
217 	}
218 
219 	/* finally connect security layer (if not already done) */
220 	if (!nego_security_connect(nego))
221 	{
222 		WLog_DBG(TAG, "Failed to connect with %s security",
223 		         protocol_security_string(nego->SelectedProtocol));
224 		return FALSE;
225 	}
226 
227 	return TRUE;
228 }
229 
nego_disconnect(rdpNego * nego)230 BOOL nego_disconnect(rdpNego* nego)
231 {
232 	nego->state = NEGO_STATE_INITIAL;
233 	return nego_transport_disconnect(nego);
234 }
235 
236 /* connect to selected security layer */
nego_security_connect(rdpNego * nego)237 BOOL nego_security_connect(rdpNego* nego)
238 {
239 	if (!nego->TcpConnected)
240 	{
241 		nego->SecurityConnected = FALSE;
242 	}
243 	else if (!nego->SecurityConnected)
244 	{
245 		if (nego->SelectedProtocol == PROTOCOL_HYBRID)
246 		{
247 			WLog_DBG(TAG, "nego_security_connect with PROTOCOL_HYBRID");
248 			nego->SecurityConnected = transport_connect_nla(nego->transport);
249 		}
250 		else if (nego->SelectedProtocol == PROTOCOL_SSL)
251 		{
252 			WLog_DBG(TAG, "nego_security_connect with PROTOCOL_SSL");
253 			nego->SecurityConnected = transport_connect_tls(nego->transport);
254 		}
255 		else if (nego->SelectedProtocol == PROTOCOL_RDP)
256 		{
257 			WLog_DBG(TAG, "nego_security_connect with PROTOCOL_RDP");
258 			nego->SecurityConnected = transport_connect_rdp(nego->transport);
259 		}
260 		else
261 		{
262 			WLog_ERR(TAG,
263 			         "cannot connect security layer because no protocol has been selected yet.");
264 		}
265 	}
266 
267 	return nego->SecurityConnected;
268 }
269 
270 /**
271  * Connect TCP layer.
272  * @param nego
273  * @return
274  */
275 
nego_tcp_connect(rdpNego * nego)276 static BOOL nego_tcp_connect(rdpNego* nego)
277 {
278 	if (!nego->TcpConnected)
279 	{
280 		const UINT32 TcpConnectTimeout = freerdp_settings_get_uint32(
281 		    nego->transport->context->settings, FreeRDP_TcpConnectTimeout);
282 
283 		if (nego->GatewayEnabled)
284 		{
285 			if (nego->GatewayBypassLocal)
286 			{
287 				/* Attempt a direct connection first, and then fallback to using the gateway */
288 				WLog_INFO(TAG,
289 				          "Detecting if host can be reached locally. - This might take some time.");
290 				WLog_INFO(TAG, "To disable auto detection use /gateway-usage-method:direct");
291 				transport_set_gateway_enabled(nego->transport, FALSE);
292 				nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
293 				                                       TcpConnectTimeout);
294 			}
295 
296 			if (!nego->TcpConnected)
297 			{
298 				transport_set_gateway_enabled(nego->transport, TRUE);
299 				nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
300 				                                       TcpConnectTimeout);
301 			}
302 		}
303 		else
304 		{
305 			nego->TcpConnected =
306 			    transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
307 		}
308 	}
309 
310 	return nego->TcpConnected;
311 }
312 
313 /**
314  * Connect TCP layer. For direct approach, connect security layer as well.
315  * @param nego
316  * @return
317  */
318 
nego_transport_connect(rdpNego * nego)319 BOOL nego_transport_connect(rdpNego* nego)
320 {
321 	if (!nego_tcp_connect(nego))
322 		return FALSE;
323 
324 	if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
325 		return nego_security_connect(nego);
326 
327 	return nego->TcpConnected;
328 }
329 
330 /**
331  * Disconnect TCP layer.
332  * @param nego
333  * @return
334  */
335 
nego_transport_disconnect(rdpNego * nego)336 BOOL nego_transport_disconnect(rdpNego* nego)
337 {
338 	if (nego->TcpConnected)
339 		transport_disconnect(nego->transport);
340 
341 	nego->TcpConnected = FALSE;
342 	nego->SecurityConnected = FALSE;
343 	return TRUE;
344 }
345 
346 /**
347  * Send preconnection information if enabled.
348  * @param nego
349  * @return
350  */
351 
nego_send_preconnection_pdu(rdpNego * nego)352 BOOL nego_send_preconnection_pdu(rdpNego* nego)
353 {
354 	wStream* s;
355 	UINT32 cbSize;
356 	UINT16 cchPCB = 0;
357 	WCHAR* wszPCB = NULL;
358 	WLog_DBG(TAG, "Sending preconnection PDU");
359 
360 	if (!nego_tcp_connect(nego))
361 		return FALSE;
362 
363 	/* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */
364 	cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
365 
366 	if (nego->PreconnectionBlob)
367 	{
368 		cchPCB = (UINT16)ConvertToUnicode(CP_UTF8, 0, nego->PreconnectionBlob, -1, &wszPCB, 0);
369 		cchPCB += 1; /* zero-termination */
370 		cbSize += cchPCB * 2;
371 	}
372 
373 	s = Stream_New(NULL, cbSize);
374 
375 	if (!s)
376 	{
377 		free(wszPCB);
378 		WLog_ERR(TAG, "Stream_New failed!");
379 		return FALSE;
380 	}
381 
382 	Stream_Write_UINT32(s, cbSize);                /* cbSize */
383 	Stream_Write_UINT32(s, 0);                     /* Flags */
384 	Stream_Write_UINT32(s, PRECONNECTION_PDU_V2);  /* Version */
385 	Stream_Write_UINT32(s, nego->PreconnectionId); /* Id */
386 	Stream_Write_UINT16(s, cchPCB);                /* cchPCB */
387 
388 	if (wszPCB)
389 	{
390 		Stream_Write(s, wszPCB, cchPCB * 2); /* wszPCB */
391 		free(wszPCB);
392 	}
393 
394 	Stream_SealLength(s);
395 
396 	if (transport_write(nego->transport, s) < 0)
397 	{
398 		Stream_Free(s, TRUE);
399 		return FALSE;
400 	}
401 
402 	Stream_Free(s, TRUE);
403 	return TRUE;
404 }
405 
406 /**
407  * Attempt negotiating NLA + TLS extended security.
408  * @param nego
409  */
410 
nego_attempt_ext(rdpNego * nego)411 static void nego_attempt_ext(rdpNego* nego)
412 {
413 	nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
414 	WLog_DBG(TAG, "Attempting NLA extended security");
415 
416 	if (!nego_transport_connect(nego))
417 	{
418 		nego->state = NEGO_STATE_FAIL;
419 		return;
420 	}
421 
422 	if (!nego_send_negotiation_request(nego))
423 	{
424 		nego->state = NEGO_STATE_FAIL;
425 		return;
426 	}
427 
428 	if (!nego_recv_response(nego))
429 	{
430 		nego->state = NEGO_STATE_FAIL;
431 		return;
432 	}
433 
434 	WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
435 
436 	if (nego->state != NEGO_STATE_FINAL)
437 	{
438 		nego_transport_disconnect(nego);
439 
440 		if (nego->EnabledProtocols[PROTOCOL_HYBRID])
441 			nego->state = NEGO_STATE_NLA;
442 		else if (nego->EnabledProtocols[PROTOCOL_SSL])
443 			nego->state = NEGO_STATE_TLS;
444 		else if (nego->EnabledProtocols[PROTOCOL_RDP])
445 			nego->state = NEGO_STATE_RDP;
446 		else
447 			nego->state = NEGO_STATE_FAIL;
448 	}
449 }
450 
451 /**
452  * Attempt negotiating NLA + TLS security.
453  * @param nego
454  */
455 
nego_attempt_nla(rdpNego * nego)456 static void nego_attempt_nla(rdpNego* nego)
457 {
458 	nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
459 	WLog_DBG(TAG, "Attempting NLA security");
460 
461 	if (!nego_transport_connect(nego))
462 	{
463 		nego->state = NEGO_STATE_FAIL;
464 		return;
465 	}
466 
467 	if (!nego_send_negotiation_request(nego))
468 	{
469 		nego->state = NEGO_STATE_FAIL;
470 		return;
471 	}
472 
473 	if (!nego_recv_response(nego))
474 	{
475 		nego->state = NEGO_STATE_FAIL;
476 		return;
477 	}
478 
479 	WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
480 
481 	if (nego->state != NEGO_STATE_FINAL)
482 	{
483 		nego_transport_disconnect(nego);
484 
485 		if (nego->EnabledProtocols[PROTOCOL_SSL])
486 			nego->state = NEGO_STATE_TLS;
487 		else if (nego->EnabledProtocols[PROTOCOL_RDP])
488 			nego->state = NEGO_STATE_RDP;
489 		else
490 			nego->state = NEGO_STATE_FAIL;
491 	}
492 }
493 
494 /**
495  * Attempt negotiating TLS security.
496  * @param nego
497  */
498 
nego_attempt_tls(rdpNego * nego)499 static void nego_attempt_tls(rdpNego* nego)
500 {
501 	nego->RequestedProtocols = PROTOCOL_SSL;
502 	WLog_DBG(TAG, "Attempting TLS security");
503 
504 	if (!nego_transport_connect(nego))
505 	{
506 		nego->state = NEGO_STATE_FAIL;
507 		return;
508 	}
509 
510 	if (!nego_send_negotiation_request(nego))
511 	{
512 		nego->state = NEGO_STATE_FAIL;
513 		return;
514 	}
515 
516 	if (!nego_recv_response(nego))
517 	{
518 		nego->state = NEGO_STATE_FAIL;
519 		return;
520 	}
521 
522 	if (nego->state != NEGO_STATE_FINAL)
523 	{
524 		nego_transport_disconnect(nego);
525 
526 		if (nego->EnabledProtocols[PROTOCOL_RDP])
527 			nego->state = NEGO_STATE_RDP;
528 		else
529 			nego->state = NEGO_STATE_FAIL;
530 	}
531 }
532 
533 /**
534  * Attempt negotiating standard RDP security.
535  * @param nego
536  */
537 
nego_attempt_rdp(rdpNego * nego)538 static void nego_attempt_rdp(rdpNego* nego)
539 {
540 	nego->RequestedProtocols = PROTOCOL_RDP;
541 	WLog_DBG(TAG, "Attempting RDP security");
542 
543 	if (!nego_transport_connect(nego))
544 	{
545 		nego->state = NEGO_STATE_FAIL;
546 		return;
547 	}
548 
549 	if (!nego_send_negotiation_request(nego))
550 	{
551 		nego->state = NEGO_STATE_FAIL;
552 		return;
553 	}
554 
555 	if (!nego_recv_response(nego))
556 	{
557 		nego->state = NEGO_STATE_FAIL;
558 		return;
559 	}
560 }
561 
562 /**
563  * Wait to receive a negotiation response
564  * @param nego
565  */
566 
nego_recv_response(rdpNego * nego)567 BOOL nego_recv_response(rdpNego* nego)
568 {
569 	int status;
570 	wStream* s;
571 	s = Stream_New(NULL, 1024);
572 
573 	if (!s)
574 	{
575 		WLog_ERR(TAG, "Stream_New failed!");
576 		return FALSE;
577 	}
578 
579 	status = transport_read_pdu(nego->transport, s);
580 
581 	if (status < 0)
582 	{
583 		Stream_Free(s, TRUE);
584 		return FALSE;
585 	}
586 
587 	status = nego_recv(nego->transport, s, nego);
588 	Stream_Free(s, TRUE);
589 
590 	if (status < 0)
591 		return FALSE;
592 
593 	return TRUE;
594 }
595 
596 /**
597  * Receive protocol security negotiation message.\n
598  * @msdn{cc240501}
599  * @param transport transport
600  * @param s stream
601  * @param extra nego pointer
602  */
603 
nego_recv(rdpTransport * transport,wStream * s,void * extra)604 int nego_recv(rdpTransport* transport, wStream* s, void* extra)
605 {
606 	BYTE li;
607 	BYTE type;
608 	UINT16 length;
609 	rdpNego* nego = (rdpNego*)extra;
610 
611 	if (!tpkt_read_header(s, &length))
612 		return -1;
613 
614 	if (!tpdu_read_connection_confirm(s, &li, length))
615 		return -1;
616 
617 	if (li > 6)
618 	{
619 		/* rdpNegData (optional) */
620 		Stream_Read_UINT8(s, type); /* Type */
621 
622 		switch (type)
623 		{
624 			case TYPE_RDP_NEG_RSP:
625 				if (!nego_process_negotiation_response(nego, s))
626 					return -1;
627 				WLog_DBG(TAG, "selected_protocol: %" PRIu32 "", nego->SelectedProtocol);
628 
629 				/* enhanced security selected ? */
630 
631 				if (nego->SelectedProtocol)
632 				{
633 					if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
634 					    (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
635 					{
636 						nego->state = NEGO_STATE_FAIL;
637 					}
638 
639 					if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
640 					    (!nego->EnabledProtocols[PROTOCOL_SSL]))
641 					{
642 						nego->state = NEGO_STATE_FAIL;
643 					}
644 				}
645 				else if (!nego->EnabledProtocols[PROTOCOL_RDP])
646 				{
647 					nego->state = NEGO_STATE_FAIL;
648 				}
649 
650 				break;
651 
652 			case TYPE_RDP_NEG_FAILURE:
653 				if (!nego_process_negotiation_failure(nego, s))
654 					return -1;
655 				break;
656 		}
657 	}
658 	else if (li == 6)
659 	{
660 		WLog_DBG(TAG, "no rdpNegData");
661 
662 		if (!nego->EnabledProtocols[PROTOCOL_RDP])
663 			nego->state = NEGO_STATE_FAIL;
664 		else
665 			nego->state = NEGO_STATE_FINAL;
666 	}
667 	else
668 	{
669 		WLog_ERR(TAG, "invalid negotiation response");
670 		nego->state = NEGO_STATE_FAIL;
671 	}
672 
673 	if (!tpkt_ensure_stream_consumed(s, length))
674 		return -1;
675 	return 0;
676 }
677 
678 /**
679  * Read optional routing token or cookie of X.224 Connection Request PDU.
680  * @msdn{cc240470}
681  * @param nego
682  * @param s stream
683  */
684 
nego_read_request_token_or_cookie(rdpNego * nego,wStream * s)685 static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s)
686 {
687 	/* routingToken and cookie are optional and mutually exclusive!
688 	 *
689 	 * routingToken (variable): An optional and variable-length routing
690 	 * token (used for load balancing) terminated by a 0x0D0A two-byte
691 	 * sequence: (check [MSFT-SDLBTS] for details!)
692 	 * Cookie:[space]msts=[ip address].[port].[reserved][\x0D\x0A]
693 	 *
694 	 * cookie (variable): An optional and variable-length ANSI character
695 	 * string terminated by a 0x0D0A two-byte sequence:
696 	 * Cookie:[space]mstshash=[ANSISTRING][\x0D\x0A]
697 	 */
698 	BYTE* str = NULL;
699 	UINT16 crlf = 0;
700 	size_t pos, len;
701 	BOOL result = FALSE;
702 	BOOL isToken = FALSE;
703 	size_t remain = Stream_GetRemainingLength(s);
704 	str = Stream_Pointer(s);
705 	pos = Stream_GetPosition(s);
706 
707 	/* minimum length for token is 15 */
708 	if (remain < 15)
709 		return TRUE;
710 
711 	if (memcmp(Stream_Pointer(s), "Cookie: mstshash=", 17) != 0)
712 	{
713 		isToken = TRUE;
714 	}
715 	else
716 	{
717 		/* not a token, minimum length for cookie is 19 */
718 		if (remain < 19)
719 			return TRUE;
720 
721 		Stream_Seek(s, 17);
722 	}
723 
724 	while ((remain = Stream_GetRemainingLength(s)) >= 2)
725 	{
726 		Stream_Read_UINT16(s, crlf);
727 
728 		if (crlf == 0x0A0D)
729 			break;
730 
731 		Stream_Rewind(s, 1);
732 	}
733 
734 	if (crlf == 0x0A0D)
735 	{
736 		Stream_Rewind(s, 2);
737 		len = Stream_GetPosition(s) - pos;
738 		remain = Stream_GetRemainingLength(s);
739 		Stream_Write_UINT16(s, 0);
740 
741 		if (strnlen((char*)str, len) == len)
742 		{
743 			if (isToken)
744 				result = nego_set_routing_token(nego, str, len);
745 			else
746 				result = nego_set_cookie(nego, (char*)str);
747 		}
748 	}
749 
750 	if (!result)
751 	{
752 		Stream_SetPosition(s, pos);
753 		WLog_ERR(TAG, "invalid %s received", isToken ? "routing token" : "cookie");
754 	}
755 	else
756 	{
757 		WLog_DBG(TAG, "received %s [%s]", isToken ? "routing token" : "cookie", str);
758 	}
759 
760 	return result;
761 }
762 
763 /**
764  * Read protocol security negotiation request message.\n
765  * @param nego
766  * @param s stream
767  */
768 
nego_read_request(rdpNego * nego,wStream * s)769 BOOL nego_read_request(rdpNego* nego, wStream* s)
770 {
771 	BYTE li;
772 	BYTE type;
773 	UINT16 length;
774 
775 	if (!tpkt_read_header(s, &length))
776 		return FALSE;
777 
778 	if (!tpdu_read_connection_request(s, &li, length))
779 		return FALSE;
780 
781 	if (li != Stream_GetRemainingLength(s) + 6)
782 	{
783 		WLog_ERR(TAG, "Incorrect TPDU length indicator.");
784 		return FALSE;
785 	}
786 
787 	if (!nego_read_request_token_or_cookie(nego, s))
788 	{
789 		WLog_ERR(TAG, "Failed to parse routing token or cookie.");
790 		return FALSE;
791 	}
792 
793 	if (Stream_GetRemainingLength(s) >= 8)
794 	{
795 		/* rdpNegData (optional) */
796 		Stream_Read_UINT8(s, type); /* Type */
797 
798 		if (type != TYPE_RDP_NEG_REQ)
799 		{
800 			WLog_ERR(TAG, "Incorrect negotiation request type %" PRIu8 "", type);
801 			return FALSE;
802 		}
803 
804 		if (!nego_process_negotiation_request(nego, s))
805 			return FALSE;
806 	}
807 
808 	return tpkt_ensure_stream_consumed(s, length);
809 }
810 
811 /**
812  * Send protocol security negotiation message.
813  * @param nego
814  */
815 
nego_send(rdpNego * nego)816 void nego_send(rdpNego* nego)
817 {
818 	if (nego->state == NEGO_STATE_EXT)
819 		nego_attempt_ext(nego);
820 	else if (nego->state == NEGO_STATE_NLA)
821 		nego_attempt_nla(nego);
822 	else if (nego->state == NEGO_STATE_TLS)
823 		nego_attempt_tls(nego);
824 	else if (nego->state == NEGO_STATE_RDP)
825 		nego_attempt_rdp(nego);
826 	else
827 		WLog_ERR(TAG, "invalid negotiation state for sending");
828 }
829 
830 /**
831  * Send RDP Negotiation Request (RDP_NEG_REQ).\n
832  * @msdn{cc240500}\n
833  * @msdn{cc240470}
834  * @param nego
835  */
836 
nego_send_negotiation_request(rdpNego * nego)837 BOOL nego_send_negotiation_request(rdpNego* nego)
838 {
839 	BOOL rc = FALSE;
840 	wStream* s;
841 	size_t length;
842 	size_t bm, em;
843 	BYTE flags = 0;
844 	size_t cookie_length;
845 	s = Stream_New(NULL, 512);
846 
847 	if (!s)
848 	{
849 		WLog_ERR(TAG, "Stream_New failed!");
850 		return FALSE;
851 	}
852 
853 	length = TPDU_CONNECTION_REQUEST_LENGTH;
854 	bm = Stream_GetPosition(s);
855 	Stream_Seek(s, length);
856 
857 	if (nego->RoutingToken)
858 	{
859 		Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
860 
861 		/* Ensure Routing Token is correctly terminated - may already be present in string */
862 
863 		if ((nego->RoutingTokenLength > 2) &&
864 		    (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
865 		    (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
866 		{
867 			WLog_DBG(TAG, "Routing token looks correctly terminated - use verbatim");
868 			length += nego->RoutingTokenLength;
869 		}
870 		else
871 		{
872 			WLog_DBG(TAG, "Adding terminating CRLF to routing token");
873 			Stream_Write_UINT8(s, 0x0D); /* CR */
874 			Stream_Write_UINT8(s, 0x0A); /* LF */
875 			length += nego->RoutingTokenLength + 2;
876 		}
877 	}
878 	else if (nego->cookie)
879 	{
880 		cookie_length = strlen(nego->cookie);
881 
882 		if (cookie_length > nego->CookieMaxLength)
883 			cookie_length = nego->CookieMaxLength;
884 
885 		Stream_Write(s, "Cookie: mstshash=", 17);
886 		Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
887 		Stream_Write_UINT8(s, 0x0D); /* CR */
888 		Stream_Write_UINT8(s, 0x0A); /* LF */
889 		length += cookie_length + 19;
890 	}
891 
892 	WLog_DBG(TAG, "RequestedProtocols: %" PRIu32 "", nego->RequestedProtocols);
893 
894 	if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
895 	{
896 		/* RDP_NEG_DATA must be present for TLS and NLA */
897 		if (nego->RestrictedAdminModeRequired)
898 			flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
899 
900 		Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
901 		Stream_Write_UINT8(s, flags);
902 		Stream_Write_UINT16(s, 8);                        /* RDP_NEG_DATA length (8) */
903 		Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */
904 		length += 8;
905 	}
906 
907 	if (length > UINT16_MAX)
908 		goto fail;
909 
910 	em = Stream_GetPosition(s);
911 	Stream_SetPosition(s, bm);
912 	tpkt_write_header(s, (UINT16)length);
913 	tpdu_write_connection_request(s, (UINT16)length - 5);
914 	Stream_SetPosition(s, em);
915 	Stream_SealLength(s);
916 	rc = (transport_write(nego->transport, s) >= 0);
917 fail:
918 	Stream_Free(s, TRUE);
919 	return rc;
920 }
921 
922 /**
923  * Process Negotiation Request from Connection Request message.
924  * @param nego
925  * @param s
926  */
927 
nego_process_negotiation_request(rdpNego * nego,wStream * s)928 BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
929 {
930 	BYTE flags;
931 	UINT16 length;
932 
933 	if (Stream_GetRemainingLength(s) < 7)
934 		return FALSE;
935 	Stream_Read_UINT8(s, flags);
936 	Stream_Read_UINT16(s, length);
937 	Stream_Read_UINT32(s, nego->RequestedProtocols);
938 	WLog_DBG(TAG, "RDP_NEG_REQ: RequestedProtocol: 0x%08" PRIX32 "", nego->RequestedProtocols);
939 	nego->state = NEGO_STATE_FINAL;
940 	return TRUE;
941 }
942 
943 /**
944  * Process Negotiation Response from Connection Confirm message.
945  * @param nego
946  * @param s
947  */
948 
nego_process_negotiation_response(rdpNego * nego,wStream * s)949 BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s)
950 {
951 	UINT16 length;
952 	WLog_DBG(TAG, "RDP_NEG_RSP");
953 
954 	if (Stream_GetRemainingLength(s) < 7)
955 	{
956 		WLog_ERR(TAG, "Invalid RDP_NEG_RSP");
957 		nego->state = NEGO_STATE_FAIL;
958 		return FALSE;
959 	}
960 
961 	Stream_Read_UINT8(s, nego->flags);
962 	Stream_Read_UINT16(s, length);
963 	Stream_Read_UINT32(s, nego->SelectedProtocol);
964 	nego->state = NEGO_STATE_FINAL;
965 	return TRUE;
966 }
967 
968 /**
969  * Process Negotiation Failure from Connection Confirm message.
970  * @param nego
971  * @param s
972  */
973 
nego_process_negotiation_failure(rdpNego * nego,wStream * s)974 BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
975 {
976 	BYTE flags;
977 	UINT16 length;
978 	UINT32 failureCode;
979 	WLog_DBG(TAG, "RDP_NEG_FAILURE");
980 	if (Stream_GetRemainingLength(s) < 7)
981 		return FALSE;
982 	Stream_Read_UINT8(s, flags);
983 	Stream_Read_UINT16(s, length);
984 	Stream_Read_UINT32(s, failureCode);
985 
986 	switch (failureCode)
987 	{
988 		case SSL_REQUIRED_BY_SERVER:
989 			WLog_WARN(TAG, "Error: SSL_REQUIRED_BY_SERVER");
990 			break;
991 
992 		case SSL_NOT_ALLOWED_BY_SERVER:
993 			WLog_WARN(TAG, "Error: SSL_NOT_ALLOWED_BY_SERVER");
994 			nego->sendNegoData = TRUE;
995 			break;
996 
997 		case SSL_CERT_NOT_ON_SERVER:
998 			WLog_ERR(TAG, "Error: SSL_CERT_NOT_ON_SERVER");
999 			nego->sendNegoData = TRUE;
1000 			break;
1001 
1002 		case INCONSISTENT_FLAGS:
1003 			WLog_ERR(TAG, "Error: INCONSISTENT_FLAGS");
1004 			break;
1005 
1006 		case HYBRID_REQUIRED_BY_SERVER:
1007 			WLog_WARN(TAG, "Error: HYBRID_REQUIRED_BY_SERVER");
1008 			break;
1009 
1010 		default:
1011 			WLog_ERR(TAG, "Error: Unknown protocol security error %" PRIu32 "", failureCode);
1012 			break;
1013 	}
1014 
1015 	nego->state = NEGO_STATE_FAIL;
1016 	return TRUE;
1017 }
1018 
1019 /**
1020  * Send RDP Negotiation Response (RDP_NEG_RSP).\n
1021  * @param nego
1022  */
1023 
nego_send_negotiation_response(rdpNego * nego)1024 BOOL nego_send_negotiation_response(rdpNego* nego)
1025 {
1026 	UINT16 length;
1027 	size_t bm, em;
1028 	BOOL status;
1029 	wStream* s;
1030 	BYTE flags;
1031 	rdpSettings* settings;
1032 	status = TRUE;
1033 	settings = nego->transport->settings;
1034 	s = Stream_New(NULL, 512);
1035 
1036 	if (!s)
1037 	{
1038 		WLog_ERR(TAG, "Stream_New failed!");
1039 		return FALSE;
1040 	}
1041 
1042 	length = TPDU_CONNECTION_CONFIRM_LENGTH;
1043 	bm = Stream_GetPosition(s);
1044 	Stream_Seek(s, length);
1045 
1046 	if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1047 	{
1048 		UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1049 		flags = 0;
1050 		Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1051 		Stream_Write_UINT8(s, flags); /* flags */
1052 		Stream_Write_UINT16(s, 8);    /* RDP_NEG_DATA length (8) */
1053 		Stream_Write_UINT32(s, errorCode);
1054 		length += 8;
1055 		status = FALSE;
1056 	}
1057 	else
1058 	{
1059 		flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1060 
1061 		if (settings->SupportGraphicsPipeline)
1062 			flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1063 
1064 		/* RDP_NEG_DATA must be present for TLS, NLA, and RDP */
1065 		Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1066 		Stream_Write_UINT8(s, flags);                   /* flags */
1067 		Stream_Write_UINT16(s, 8);                      /* RDP_NEG_DATA length (8) */
1068 		Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */
1069 		length += 8;
1070 	}
1071 
1072 	em = Stream_GetPosition(s);
1073 	Stream_SetPosition(s, bm);
1074 	status = tpkt_write_header(s, length);
1075 	if (status)
1076 	{
1077 		tpdu_write_connection_confirm(s, length - 5);
1078 		Stream_SetPosition(s, em);
1079 		Stream_SealLength(s);
1080 
1081 		status = (transport_write(nego->transport, s) >= 0);
1082 	}
1083 	Stream_Free(s, TRUE);
1084 
1085 	if (status)
1086 	{
1087 		/* update settings with negotiated protocol security */
1088 		settings->RequestedProtocols = nego->RequestedProtocols;
1089 		settings->SelectedProtocol = nego->SelectedProtocol;
1090 
1091 		if (settings->SelectedProtocol == PROTOCOL_RDP)
1092 		{
1093 			settings->TlsSecurity = FALSE;
1094 			settings->NlaSecurity = FALSE;
1095 			settings->RdpSecurity = TRUE;
1096 			settings->UseRdpSecurityLayer = TRUE;
1097 
1098 			if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
1099 			{
1100 				/**
1101 				 * If the server implementation did not explicitely set a
1102 				 * encryption level we default to client compatible
1103 				 */
1104 				settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
1105 			}
1106 
1107 			if (settings->LocalConnection)
1108 			{
1109 				/**
1110 				 * Note: This hack was firstly introduced in commit 95f5e115 to
1111 				 * disable the unnecessary encryption with peers connecting to
1112 				 * 127.0.0.1 or local unix sockets.
1113 				 * This also affects connections via port tunnels! (e.g. ssh -L)
1114 				 */
1115 				WLog_INFO(TAG, "Turning off encryption for local peer with standard rdp security");
1116 				settings->UseRdpSecurityLayer = FALSE;
1117 				settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
1118 			}
1119 
1120 			if (!settings->RdpServerRsaKey && !settings->RdpKeyFile && !settings->RdpKeyContent)
1121 			{
1122 				WLog_ERR(TAG, "Missing server certificate");
1123 				return FALSE;
1124 			}
1125 		}
1126 		else if (settings->SelectedProtocol == PROTOCOL_SSL)
1127 		{
1128 			settings->TlsSecurity = TRUE;
1129 			settings->NlaSecurity = FALSE;
1130 			settings->RdpSecurity = FALSE;
1131 			settings->UseRdpSecurityLayer = FALSE;
1132 			settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
1133 		}
1134 		else if (settings->SelectedProtocol == PROTOCOL_HYBRID)
1135 		{
1136 			settings->TlsSecurity = TRUE;
1137 			settings->NlaSecurity = TRUE;
1138 			settings->RdpSecurity = FALSE;
1139 			settings->UseRdpSecurityLayer = FALSE;
1140 			settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
1141 		}
1142 	}
1143 
1144 	return status;
1145 }
1146 
1147 /**
1148  * Initialize NEGO state machine.
1149  * @param nego
1150  */
1151 
nego_init(rdpNego * nego)1152 void nego_init(rdpNego* nego)
1153 {
1154 	nego->state = NEGO_STATE_INITIAL;
1155 	nego->RequestedProtocols = PROTOCOL_RDP;
1156 	nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
1157 	nego->sendNegoData = FALSE;
1158 	nego->flags = 0;
1159 }
1160 
1161 /**
1162  * Create a new NEGO state machine instance.
1163  * @param transport
1164  * @return
1165  */
1166 
nego_new(rdpTransport * transport)1167 rdpNego* nego_new(rdpTransport* transport)
1168 {
1169 	rdpNego* nego = (rdpNego*)calloc(1, sizeof(rdpNego));
1170 
1171 	if (!nego)
1172 		return NULL;
1173 
1174 	nego->transport = transport;
1175 	nego_init(nego);
1176 	return nego;
1177 }
1178 
1179 /**
1180  * Free NEGO state machine.
1181  * @param nego
1182  */
1183 
nego_free(rdpNego * nego)1184 void nego_free(rdpNego* nego)
1185 {
1186 	if (nego)
1187 	{
1188 		free(nego->RoutingToken);
1189 		free(nego->cookie);
1190 		free(nego);
1191 	}
1192 }
1193 
1194 /**
1195  * Set target hostname and port.
1196  * @param nego
1197  * @param hostname
1198  * @param port
1199  */
1200 
nego_set_target(rdpNego * nego,const char * hostname,UINT16 port)1201 BOOL nego_set_target(rdpNego* nego, const char* hostname, UINT16 port)
1202 {
1203 	if (!nego || !hostname)
1204 		return FALSE;
1205 
1206 	nego->hostname = hostname;
1207 	nego->port = port;
1208 	return TRUE;
1209 }
1210 
1211 /**
1212  * Enable security layer negotiation.
1213  * @param nego pointer to the negotiation structure
1214  * @param enable_rdp whether to enable security layer negotiation (TRUE for enabled, FALSE for
1215  * disabled)
1216  */
1217 
nego_set_negotiation_enabled(rdpNego * nego,BOOL NegotiateSecurityLayer)1218 void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1219 {
1220 	WLog_DBG(TAG, "Enabling security layer negotiation: %s",
1221 	         NegotiateSecurityLayer ? "TRUE" : "FALSE");
1222 	nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1223 }
1224 
1225 /**
1226  * Enable restricted admin mode.
1227  * @param nego pointer to the negotiation structure
1228  * @param enable_restricted whether to enable security layer negotiation (TRUE for enabled, FALSE
1229  * for disabled)
1230  */
1231 
nego_set_restricted_admin_mode_required(rdpNego * nego,BOOL RestrictedAdminModeRequired)1232 void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1233 {
1234 	WLog_DBG(TAG, "Enabling restricted admin mode: %s",
1235 	         RestrictedAdminModeRequired ? "TRUE" : "FALSE");
1236 	nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1237 }
1238 
nego_set_gateway_enabled(rdpNego * nego,BOOL GatewayEnabled)1239 void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1240 {
1241 	nego->GatewayEnabled = GatewayEnabled;
1242 }
1243 
nego_set_gateway_bypass_local(rdpNego * nego,BOOL GatewayBypassLocal)1244 void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1245 {
1246 	nego->GatewayBypassLocal = GatewayBypassLocal;
1247 }
1248 
1249 /**
1250  * Enable RDP security protocol.
1251  * @param nego pointer to the negotiation structure
1252  * @param enable_rdp whether to enable normal RDP protocol (TRUE for enabled, FALSE for disabled)
1253  */
1254 
nego_enable_rdp(rdpNego * nego,BOOL enable_rdp)1255 void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1256 {
1257 	WLog_DBG(TAG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE");
1258 	nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1259 }
1260 
1261 /**
1262  * Enable TLS security protocol.
1263  * @param nego pointer to the negotiation structure
1264  * @param enable_tls whether to enable TLS + RDP protocol (TRUE for enabled, FALSE for disabled)
1265  */
1266 
nego_enable_tls(rdpNego * nego,BOOL enable_tls)1267 void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1268 {
1269 	WLog_DBG(TAG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
1270 	nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1271 }
1272 
1273 /**
1274  * Enable NLA security protocol.
1275  * @param nego pointer to the negotiation structure
1276  * @param enable_nla whether to enable network level authentication protocol (TRUE for enabled,
1277  * FALSE for disabled)
1278  */
1279 
nego_enable_nla(rdpNego * nego,BOOL enable_nla)1280 void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1281 {
1282 	WLog_DBG(TAG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE");
1283 	nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1284 }
1285 
1286 /**
1287  * Enable NLA extended security protocol.
1288  * @param nego pointer to the negotiation structure
1289  * @param enable_ext whether to enable network level authentication extended protocol (TRUE for
1290  * enabled, FALSE for disabled)
1291  */
1292 
nego_enable_ext(rdpNego * nego,BOOL enable_ext)1293 void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1294 {
1295 	WLog_DBG(TAG, "Enabling NLA extended security: %s", enable_ext ? "TRUE" : "FALSE");
1296 	nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = enable_ext;
1297 }
1298 
1299 /**
1300  * Set routing token.
1301  * @param nego
1302  * @param RoutingToken
1303  * @param RoutingTokenLength
1304  */
1305 
nego_set_routing_token(rdpNego * nego,BYTE * RoutingToken,DWORD RoutingTokenLength)1306 BOOL nego_set_routing_token(rdpNego* nego, BYTE* RoutingToken, DWORD RoutingTokenLength)
1307 {
1308 	if (RoutingTokenLength == 0)
1309 		return FALSE;
1310 
1311 	free(nego->RoutingToken);
1312 	nego->RoutingTokenLength = RoutingTokenLength;
1313 	nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1314 
1315 	if (!nego->RoutingToken)
1316 		return FALSE;
1317 
1318 	CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1319 	return TRUE;
1320 }
1321 
1322 /**
1323  * Set cookie.
1324  * @param nego
1325  * @param cookie
1326  */
1327 
nego_set_cookie(rdpNego * nego,char * cookie)1328 BOOL nego_set_cookie(rdpNego* nego, char* cookie)
1329 {
1330 	if (nego->cookie)
1331 	{
1332 		free(nego->cookie);
1333 		nego->cookie = NULL;
1334 	}
1335 
1336 	if (!cookie)
1337 		return TRUE;
1338 
1339 	nego->cookie = _strdup(cookie);
1340 
1341 	if (!nego->cookie)
1342 		return FALSE;
1343 
1344 	return TRUE;
1345 }
1346 
1347 /**
1348  * Set cookie maximum length
1349  * @param nego
1350  * @param CookieMaxLength
1351  */
1352 
nego_set_cookie_max_length(rdpNego * nego,UINT32 CookieMaxLength)1353 void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
1354 {
1355 	nego->CookieMaxLength = CookieMaxLength;
1356 }
1357 
1358 /**
1359  * Enable / disable preconnection PDU.
1360  * @param nego
1361  * @param send_pcpdu
1362  */
1363 
nego_set_send_preconnection_pdu(rdpNego * nego,BOOL SendPreconnectionPdu)1364 void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
1365 {
1366 	nego->SendPreconnectionPdu = SendPreconnectionPdu;
1367 }
1368 
1369 /**
1370  * Set preconnection id.
1371  * @param nego
1372  * @param id
1373  */
1374 
nego_set_preconnection_id(rdpNego * nego,UINT32 PreconnectionId)1375 void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
1376 {
1377 	nego->PreconnectionId = PreconnectionId;
1378 }
1379 
1380 /**
1381  * Set preconnection blob.
1382  * @param nego
1383  * @param blob
1384  */
1385 
nego_set_preconnection_blob(rdpNego * nego,char * PreconnectionBlob)1386 void nego_set_preconnection_blob(rdpNego* nego, char* PreconnectionBlob)
1387 {
1388 	nego->PreconnectionBlob = PreconnectionBlob;
1389 }
1390 
nego_get_selected_protocol(rdpNego * nego)1391 UINT32 nego_get_selected_protocol(rdpNego* nego)
1392 {
1393 	if (!nego)
1394 		return 0;
1395 
1396 	return nego->SelectedProtocol;
1397 }
1398 
nego_set_selected_protocol(rdpNego * nego,UINT32 SelectedProtocol)1399 BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
1400 {
1401 	if (!nego)
1402 		return FALSE;
1403 
1404 	nego->SelectedProtocol = SelectedProtocol;
1405 	return TRUE;
1406 }
1407 
nego_get_requested_protocols(rdpNego * nego)1408 UINT32 nego_get_requested_protocols(rdpNego* nego)
1409 {
1410 	if (!nego)
1411 		return 0;
1412 
1413 	return nego->RequestedProtocols;
1414 }
1415 
nego_set_requested_protocols(rdpNego * nego,UINT32 RequestedProtocols)1416 BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
1417 {
1418 	if (!nego)
1419 		return FALSE;
1420 
1421 	nego->RequestedProtocols = RequestedProtocols;
1422 	return TRUE;
1423 }
1424 
nego_get_state(rdpNego * nego)1425 NEGO_STATE nego_get_state(rdpNego* nego)
1426 {
1427 	if (!nego)
1428 		return NEGO_STATE_FAIL;
1429 
1430 	return nego->state;
1431 }
1432 
nego_set_state(rdpNego * nego,NEGO_STATE state)1433 BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
1434 {
1435 	if (!nego)
1436 		return FALSE;
1437 
1438 	nego->state = state;
1439 	return TRUE;
1440 }
1441 
nego_get_identity(rdpNego * nego)1442 SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
1443 {
1444 	if (!nego)
1445 		return NULL;
1446 
1447 	return nla_get_identity(nego->transport->nla);
1448 }
1449 
nego_free_nla(rdpNego * nego)1450 void nego_free_nla(rdpNego* nego)
1451 {
1452 	if (!nego || !nego->transport)
1453 		return;
1454 
1455 	nla_free(nego->transport->nla);
1456 	nego->transport->nla = NULL;
1457 }
1458 
nego_get_routing_token(rdpNego * nego,DWORD * RoutingTokenLength)1459 const BYTE* nego_get_routing_token(rdpNego* nego, DWORD* RoutingTokenLength)
1460 {
1461 	if (!nego)
1462 		return NULL;
1463 	if (RoutingTokenLength)
1464 		*RoutingTokenLength = nego->RoutingTokenLength;
1465 	return nego->RoutingToken;
1466 }
1467