7eb810bba9d6a8056d3bc9697c5ced215b36692a
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / nego.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * RDP Protocol Security Negotiation
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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 #include <stdio.h>
21 #include <string.h>
22
23 #include <freerdp/constants.h>
24 #include <freerdp/utils/memory.h>
25
26 #include "tpkt.h"
27
28 #include "nego.h"
29
30 static const char* const NEGO_STATE_STRINGS[] =
31 {
32         "NEGO_STATE_INITIAL",
33         "NEGO_STATE_NLA",
34         "NEGO_STATE_TLS",
35         "NEGO_STATE_RDP",
36         "NEGO_STATE_FAIL",
37         "NEGO_STATE_FINAL"
38 };
39
40 static const char PROTOCOL_SECURITY_STRINGS[3][4] =
41 {
42         "RDP",
43         "TLS",
44         "NLA"
45 };
46
47 /**
48  * Negotiate protocol security and connect.
49  * @param nego
50  * @return
51  */
52
53 boolean nego_connect(rdpNego* nego)
54 {
55         if (nego->state == NEGO_STATE_INITIAL)
56         {
57                 if (nego->enabled_protocols[PROTOCOL_NLA] > 0)
58                         nego->state = NEGO_STATE_NLA;
59                 else if (nego->enabled_protocols[PROTOCOL_TLS] > 0)
60                         nego->state = NEGO_STATE_TLS;
61                 else if (nego->enabled_protocols[PROTOCOL_RDP] > 0)
62                         nego->state = NEGO_STATE_RDP;
63                 else
64                         nego->state = NEGO_STATE_FAIL;
65         }
66
67         do
68         {
69                 DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]);
70
71                 nego_send(nego);
72
73                 if (nego->state == NEGO_STATE_FAIL)
74                 {
75                         DEBUG_NEGO("Protocol Security Negotiation Failure");
76                         nego->state = NEGO_STATE_FINAL;
77                         return false;
78                 }
79         }
80         while (nego->state != NEGO_STATE_FINAL);
81
82         DEBUG_NEGO("Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]);
83
84         /* update settings with negotiated protocol security */
85         nego->transport->settings->requested_protocols = nego->requested_protocols;
86         nego->transport->settings->selected_protocol = nego->selected_protocol;
87         nego->transport->settings->negotiationFlags = nego->flags;
88
89         if(nego->selected_protocol == PROTOCOL_RDP)
90         {
91                 nego->transport->settings->encryption = true;
92                 nego->transport->settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
93                 nego->transport->settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
94         }
95
96         return true;
97 }
98
99 /**
100  * Connect TCP layer.
101  * @param nego
102  * @return
103  */
104
105 boolean nego_tcp_connect(rdpNego* nego)
106 {
107         if (nego->tcp_connected == 0)
108         {
109                 if (transport_connect(nego->transport, nego->hostname, nego->port) == false)
110                 {
111                         nego->tcp_connected = 0;
112                         return false;
113                 }
114                 else
115                 {
116                         nego->tcp_connected = 1;
117                         return true;
118                 }
119         }
120
121         return true;
122 }
123
124 /**
125  * Disconnect TCP layer.
126  * @param nego
127  * @return
128  */
129
130 int nego_tcp_disconnect(rdpNego* nego)
131 {
132         if (nego->tcp_connected)
133                 transport_disconnect(nego->transport);
134
135         nego->tcp_connected = 0;
136         return 1;
137 }
138
139 /**
140  * Attempt negotiating NLA + TLS security.
141  * @param nego
142  */
143
144 void nego_attempt_nla(rdpNego* nego)
145 {
146         nego->requested_protocols = PROTOCOL_NLA | PROTOCOL_TLS;
147
148         DEBUG_NEGO("Attempting NLA security");
149
150         if (!nego_tcp_connect(nego))
151         {
152                 nego->state = NEGO_STATE_FAIL;
153                 return;
154         }
155
156         if (!nego_send_negotiation_request(nego))
157         {
158                 nego->state = NEGO_STATE_FAIL;
159                 return;
160         }
161
162         if (!nego_recv_response(nego))
163         {
164                 nego->state = NEGO_STATE_FAIL;
165                 return;
166         }
167
168         if (nego->state != NEGO_STATE_FINAL)
169         {
170                 nego_tcp_disconnect(nego);
171
172                 if (nego->enabled_protocols[PROTOCOL_TLS] > 0)
173                         nego->state = NEGO_STATE_TLS;
174                 else if (nego->enabled_protocols[PROTOCOL_RDP] > 0)
175                         nego->state = NEGO_STATE_RDP;
176                 else
177                         nego->state = NEGO_STATE_FAIL;
178         }
179 }
180
181 /**
182  * Attempt negotiating TLS security.
183  * @param nego
184  */
185
186 void nego_attempt_tls(rdpNego* nego)
187 {
188         nego->requested_protocols = PROTOCOL_TLS;
189
190         DEBUG_NEGO("Attempting TLS security");
191
192         if (!nego_tcp_connect(nego))
193         {
194                 nego->state = NEGO_STATE_FAIL;
195                 return;
196         }
197
198         if (!nego_send_negotiation_request(nego))
199         {
200                 nego->state = NEGO_STATE_FAIL;
201                 return;
202         }
203
204         if (!nego_recv_response(nego))
205         {
206                 nego->state = NEGO_STATE_FAIL;
207                 return;
208         }
209
210         if (nego->state != NEGO_STATE_FINAL)
211         {
212                 nego_tcp_disconnect(nego);
213
214                 if (nego->enabled_protocols[PROTOCOL_RDP] > 0)
215                         nego->state = NEGO_STATE_RDP;
216                 else
217                         nego->state = NEGO_STATE_FAIL;
218         }
219 }
220
221 /**
222  * Attempt negotiating standard RDP security.
223  * @param nego
224  */
225
226 void nego_attempt_rdp(rdpNego* nego)
227 {
228         nego->requested_protocols = PROTOCOL_RDP;
229
230         DEBUG_NEGO("Attempting RDP security");
231
232         if (!nego_tcp_connect(nego))
233         {
234                 nego->state = NEGO_STATE_FAIL;
235                 return;
236         }
237
238         if (!nego_send_negotiation_request(nego))
239         {
240                 nego->state = NEGO_STATE_FAIL;
241                 return;
242         }
243
244         if (!nego_recv_response(nego))
245         {
246                 nego->state = NEGO_STATE_FAIL;
247                 return;
248         }
249 }
250
251 /**
252  * Wait to receive a negotiation response
253  * @param nego
254  */
255
256 boolean nego_recv_response(rdpNego* nego)
257 {
258         STREAM* s = transport_recv_stream_init(nego->transport, 1024);
259         if (transport_read(nego->transport, s) < 0)
260                 return false;
261         return nego_recv(nego->transport, s, nego->transport->recv_extra);
262 }
263
264 /**
265  * Receive protocol security negotiation message.\n
266  * @msdn{cc240501}
267  * @param transport transport
268  * @param s stream
269  * @param extra nego pointer
270  */
271
272 boolean nego_recv(rdpTransport* transport, STREAM* s, void* extra)
273 {
274         uint8 li;
275         uint8 type;
276         rdpNego* nego = (rdpNego*) extra;
277
278         if (tpkt_read_header(s) == 0)
279                 return false;
280
281         li = tpdu_read_connection_confirm(s);
282
283         if (li > 6)
284         {
285                 /* rdpNegData (optional) */
286
287                 stream_read_uint8(s, type); /* Type */
288
289                 switch (type)
290                 {
291                         case TYPE_RDP_NEG_RSP:
292                                 nego_process_negotiation_response(nego, s);
293                                 break;
294
295                         case TYPE_RDP_NEG_FAILURE:
296                                 nego_process_negotiation_failure(nego, s);
297                                 break;
298                 }
299         }
300         else
301         {
302                 nego->state = NEGO_STATE_FINAL;
303         }
304
305         return true;
306 }
307
308 /**
309  * Read protocol security negotiation request message.\n
310  * @param nego
311  * @param s stream
312  */
313
314 boolean nego_read_request(rdpNego* nego, STREAM* s)
315 {
316         uint8 li;
317         uint8 c;
318         uint8 type;
319
320         tpkt_read_header(s);
321         li = tpdu_read_connection_request(s);
322         if (li != stream_get_left(s) + 6)
323         {
324                 printf("Incorrect TPDU length indicator.\n");
325                 return false;
326         }
327
328         if (stream_get_left(s) > 8)
329         {
330                 /* Optional routingToken or cookie, ending with CR+LF */
331                 while (stream_get_left(s) > 0)
332                 {
333                         stream_read_uint8(s, c);
334                         if (c != '\x0D')
335                                 continue;
336                         stream_peek_uint8(s, c);
337                         if (c != '\x0A')
338                                 continue;
339
340                         stream_seek_uint8(s);
341                         break;
342                 }
343         }
344
345         if (stream_get_left(s) >= 8)
346         {
347                 /* rdpNegData (optional) */
348
349                 stream_read_uint8(s, type); /* Type */
350                 if (type != TYPE_RDP_NEG_REQ)
351                 {
352                         printf("Incorrect negotiation request type %d\n", type);
353                         return false;
354                 }
355
356                 nego_process_negotiation_request(nego, s);
357         }
358
359         return true;
360 }
361
362 /**
363  * Send protocol security negotiation message.
364  * @param nego
365  */
366
367 void nego_send(rdpNego* nego)
368 {
369         if (nego->state == NEGO_STATE_NLA)
370                 nego_attempt_nla(nego);
371         else if (nego->state == NEGO_STATE_TLS)
372                 nego_attempt_tls(nego);
373         else if (nego->state == NEGO_STATE_RDP)
374                 nego_attempt_rdp(nego);
375         else
376                 DEBUG_NEGO("invalid negotiation state for sending");
377 }
378
379 /**
380  * Send RDP Negotiation Request (RDP_NEG_REQ).\n
381  * @msdn{cc240500}\n
382  * @msdn{cc240470}
383  * @param nego
384  */
385
386 boolean nego_send_negotiation_request(rdpNego* nego)
387 {
388         STREAM* s;
389         int length;
390         uint8 *bm, *em;
391
392         s = transport_send_stream_init(nego->transport, 256);
393         length = TPDU_CONNECTION_REQUEST_LENGTH;
394         stream_get_mark(s, bm);
395         stream_seek(s, length);
396
397         if (nego->routing_token != NULL)
398         {
399                 stream_write(s, nego->routing_token->data, nego->routing_token->length);
400                 length += nego->routing_token->length;
401         }
402         else if (nego->cookie != NULL)
403         {
404                 int cookie_length = strlen(nego->cookie);
405                 stream_write(s, "Cookie: mstshash=", 17);
406                 stream_write(s, (uint8*)nego->cookie, cookie_length);
407                 stream_write_uint8(s, 0x0D); /* CR */
408                 stream_write_uint8(s, 0x0A); /* LF */
409                 length += cookie_length + 19;
410         }
411
412         if (nego->requested_protocols > PROTOCOL_RDP)
413         {
414                 /* RDP_NEG_DATA must be present for TLS and NLA */
415                 stream_write_uint8(s, TYPE_RDP_NEG_REQ);
416                 stream_write_uint8(s, 0); /* flags, must be set to zero */
417                 stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */
418                 stream_write_uint32(s, nego->requested_protocols); /* requestedProtocols */
419                 length += 8;
420         }
421
422         stream_get_mark(s, em);
423         stream_set_mark(s, bm);
424         tpkt_write_header(s, length);
425         tpdu_write_connection_request(s, length - 5);
426         stream_set_mark(s, em);
427
428         if (transport_write(nego->transport, s) < 0)
429                 return false;
430
431         return true;
432 }
433
434 /**
435  * Process Negotiation Request from Connection Request message.
436  * @param nego
437  * @param s
438  */
439
440 void nego_process_negotiation_request(rdpNego* nego, STREAM* s)
441 {
442         uint8 flags;
443         uint16 length;
444
445         DEBUG_NEGO("RDP_NEG_REQ");
446
447         stream_read_uint8(s, flags);
448         stream_read_uint16(s, length);
449         stream_read_uint32(s, nego->requested_protocols);
450
451         nego->state = NEGO_STATE_FINAL;
452 }
453
454 /**
455  * Process Negotiation Response from Connection Confirm message.
456  * @param nego
457  * @param s
458  */
459
460 void nego_process_negotiation_response(rdpNego* nego, STREAM* s)
461 {
462         uint16 length;
463
464         DEBUG_NEGO("RDP_NEG_RSP");
465
466         stream_read_uint8(s, nego->flags);
467         stream_read_uint16(s, length);
468         stream_read_uint32(s, nego->selected_protocol);
469
470         nego->state = NEGO_STATE_FINAL;
471 }
472
473 /**
474  * Process Negotiation Failure from Connection Confirm message.
475  * @param nego
476  * @param s
477  */
478
479 void nego_process_negotiation_failure(rdpNego* nego, STREAM* s)
480 {
481         uint8 flags;
482         uint16 length;
483         uint32 failureCode;
484
485         DEBUG_NEGO("RDP_NEG_FAILURE");
486
487         stream_read_uint8(s, flags);
488         stream_read_uint16(s, length);
489         stream_read_uint32(s, failureCode);
490
491         switch (failureCode)
492         {
493                 case SSL_REQUIRED_BY_SERVER:
494                         DEBUG_NEGO("Error: SSL_REQUIRED_BY_SERVER");
495                         break;
496                 case SSL_NOT_ALLOWED_BY_SERVER:
497                         DEBUG_NEGO("Error: SSL_NOT_ALLOWED_BY_SERVER");
498                         break;
499                 case SSL_CERT_NOT_ON_SERVER:
500                         DEBUG_NEGO("Error: SSL_CERT_NOT_ON_SERVER");
501                         break;
502                 case INCONSISTENT_FLAGS:
503                         DEBUG_NEGO("Error: INCONSISTENT_FLAGS");
504                         break;
505                 case HYBRID_REQUIRED_BY_SERVER:
506                         DEBUG_NEGO("Error: HYBRID_REQUIRED_BY_SERVER");
507                         break;
508                 default:
509                         DEBUG_NEGO("Error: Unknown protocol security error %d", failureCode);
510                         break;
511         }
512
513         nego->state = NEGO_STATE_FAIL;
514 }
515
516 /**
517  * Send RDP Negotiation Response (RDP_NEG_RSP).\n
518  * @param nego
519  */
520
521 boolean nego_send_negotiation_response(rdpNego* nego)
522 {
523         STREAM* s;
524         rdpSettings* settings;
525         int length;
526         uint8 *bm, *em;
527         boolean ret;
528
529         ret = true;
530         settings = nego->transport->settings;
531
532         s = transport_send_stream_init(nego->transport, 256);
533         length = TPDU_CONNECTION_CONFIRM_LENGTH;
534         stream_get_mark(s, bm);
535         stream_seek(s, length);
536
537         if (nego->selected_protocol > PROTOCOL_RDP)
538         {
539                 /* RDP_NEG_DATA must be present for TLS and NLA */
540                 stream_write_uint8(s, TYPE_RDP_NEG_RSP);
541                 stream_write_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */
542                 stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */
543                 stream_write_uint32(s, nego->selected_protocol); /* selectedProtocol */
544                 length += 8;
545         }
546         else if (!settings->rdp_security)
547         {
548                 stream_write_uint8(s, TYPE_RDP_NEG_FAILURE);
549                 stream_write_uint8(s, 0); /* flags */
550                 stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */
551                 /*
552                  * TODO: Check for other possibilities,
553                  *       like SSL_NOT_ALLOWED_BY_SERVER.
554                  */
555                 printf("nego_send_negotiation_response: client supports only Standard RDP Security\n");
556                 stream_write_uint32(s, SSL_REQUIRED_BY_SERVER);
557                 length += 8;
558                 ret = false;
559         }
560
561         stream_get_mark(s, em);
562         stream_set_mark(s, bm);
563         tpkt_write_header(s, length);
564         tpdu_write_connection_confirm(s, length - 5);
565         stream_set_mark(s, em);
566
567         if (transport_write(nego->transport, s) < 0)
568                 return false;
569
570         if (ret)
571         {
572                 /* update settings with negotiated protocol security */
573                 settings->requested_protocols = nego->requested_protocols;
574                 settings->selected_protocol = nego->selected_protocol;
575
576                 if (settings->selected_protocol == PROTOCOL_RDP)
577                 {
578                         settings->tls_security = false;
579                         settings->nla_security = false;
580                         settings->rdp_security = true;
581                         settings->encryption = true;
582                         settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
583                         settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
584                 }
585                 else if (settings->selected_protocol == PROTOCOL_TLS)
586                 {
587                         settings->tls_security = true;
588                         settings->nla_security = false;
589                         settings->rdp_security = false;
590                         settings->encryption = false;
591                         settings->encryption_method = ENCRYPTION_METHOD_NONE;
592                         settings->encryption_level = ENCRYPTION_LEVEL_NONE;
593                 }
594                 else if (settings->selected_protocol == PROTOCOL_NLA)
595                 {
596                         settings->tls_security = true;
597                         settings->nla_security = true;
598                         settings->rdp_security = false;
599                         settings->encryption = false;
600                         settings->encryption_method = ENCRYPTION_METHOD_NONE;
601                         settings->encryption_level = ENCRYPTION_LEVEL_NONE;
602                 }
603         }
604
605         return ret;
606 }
607
608 /**
609  * Initialize NEGO state machine.
610  * @param nego
611  */
612
613 void nego_init(rdpNego* nego)
614 {
615         nego->state = NEGO_STATE_INITIAL;
616         nego->requested_protocols = PROTOCOL_RDP;
617         nego->transport->recv_callback = nego_recv;
618         nego->transport->recv_extra = (void*) nego;
619         nego->flags = 0;
620 }
621
622 /**
623  * Create a new NEGO state machine instance.
624  * @param transport
625  * @return
626  */
627
628 rdpNego* nego_new(struct rdp_transport * transport)
629 {
630         rdpNego* nego = (rdpNego*) xzalloc(sizeof(rdpNego));
631
632         if (nego != NULL)
633         {
634                 nego->transport = transport;
635                 nego_init(nego);
636         }
637
638         return nego;
639 }
640
641 /**
642  * Free NEGO state machine.
643  * @param nego
644  */
645
646 void nego_free(rdpNego* nego)
647 {
648         xfree(nego);
649 }
650
651 /**
652  * Set target hostname and port.
653  * @param nego
654  * @param hostname
655  * @param port
656  */
657
658 void nego_set_target(rdpNego* nego, char* hostname, int port)
659 {
660         nego->hostname = hostname;
661         nego->port = port;
662 }
663
664 /**
665  * Enable RDP security protocol.
666  * @param nego pointer to the negotiation structure
667  * @param enable_rdp whether to enable normal RDP protocol (true for enabled, false for disabled)
668  */
669
670 void nego_enable_rdp(rdpNego* nego, boolean enable_rdp)
671 {
672         DEBUG_NEGO("Enabling RDP security: %s", enable_rdp ? "true" : "false");
673         nego->enabled_protocols[PROTOCOL_RDP] = enable_rdp;
674 }
675
676 /**
677  * Enable TLS security protocol.
678  * @param nego pointer to the negotiation structure
679  * @param enable_tls whether to enable TLS + RDP protocol (true for enabled, false for disabled)
680  */
681 void nego_enable_tls(rdpNego* nego, boolean enable_tls)
682 {
683         DEBUG_NEGO("Enabling TLS security: %s", enable_tls ? "true" : "false");
684         nego->enabled_protocols[PROTOCOL_TLS] = enable_tls;
685 }
686
687
688 /**
689  * Enable NLA security protocol.
690  * @param nego pointer to the negotiation structure
691  * @param enable_nla whether to enable network level authentication protocol (true for enabled, false for disabled)
692  */
693
694 void nego_enable_nla(rdpNego* nego, boolean enable_nla)
695 {
696         DEBUG_NEGO("Enabling NLA security: %s", enable_nla ? "true" : "false");
697         nego->enabled_protocols[PROTOCOL_NLA] = enable_nla;
698 }
699
700 /**
701  * Set routing token.
702  * @param nego
703  * @param routing_token
704  */
705
706 void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token)
707 {
708         nego->routing_token = routing_token;
709 }
710
711 /**
712  * Set cookie.
713  * @param nego
714  * @param cookie
715  */
716
717 void nego_set_cookie(rdpNego* nego, char* cookie)
718 {
719         nego->cookie = cookie;
720 }