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