6e73f9faa35d6707ead5cb84b06724da32a13341
[platform/upstream/freerdp.git] / libfreerdp / core / gateway / rdg.c
1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Remote Desktop Gateway (RDG)
4 *
5 * Copyright 2015 Denis Vincent <dvincent@devolutions.net>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <assert.h>
25
26 #include <winpr/crt.h>
27 #include <winpr/synch.h>
28 #include <winpr/print.h>
29 #include <winpr/stream.h>
30 #include <winpr/winsock.h>
31
32 #include <freerdp/log.h>
33 #include <freerdp/error.h>
34 #include <freerdp/utils/ringbuffer.h>
35
36 #include "rdg.h"
37 #include "../rdp.h"
38
39 #define TAG FREERDP_TAG("core.gateway.rdg")
40
41 #pragma pack(push, 1)
42
43 typedef struct rdg_packet_header
44 {
45         UINT16 type;
46         UINT16 reserved;
47         UINT32 packetLength;
48 } RdgPacketHeader;
49
50 #pragma pack(pop)
51
52 BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket)
53 {
54         int status;
55         wStream* sChunk;
56         char chunkSize[11];
57
58         sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", (unsigned int) Stream_Length(sPacket));
59         sChunk = Stream_New(NULL, strlen(chunkSize) + Stream_Length(sPacket) + 2);
60
61         if (!sChunk)
62                 return FALSE;
63
64         Stream_Write(sChunk, chunkSize, strlen(chunkSize));
65         Stream_Write(sChunk, Stream_Buffer(sPacket), Stream_Length(sPacket));
66         Stream_Write(sChunk, "\r\n", 2);
67         Stream_SealLength(sChunk);
68
69         status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
70         Stream_Free(sChunk, TRUE);
71
72         if (status < 0)
73                 return FALSE;
74
75         return TRUE;
76 }
77
78 wStream* rdg_receive_packet(rdpRdg* rdg)
79 {
80         int status;
81         wStream* s;
82         RdgPacketHeader* packet;
83         UINT32 readCount = 0;
84
85         s = Stream_New(NULL, 1024);
86
87         if (!s)
88                 return NULL;
89
90         packet = (RdgPacketHeader*) Stream_Buffer(s);
91
92         while (readCount < sizeof(RdgPacketHeader))
93         {
94                 status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);
95
96                 if (status < 0)
97                 {
98                         continue;
99                 }
100
101                 readCount += status;
102                 Stream_Seek(s, readCount);
103         }
104
105         if (Stream_Capacity(s) < packet->packetLength)
106         {
107                 if (!Stream_EnsureCapacity(s, packet->packetLength))
108                 {
109                         Stream_Free(s, TRUE);
110                         return NULL;
111                 }
112                 packet = (RdgPacketHeader*) Stream_Buffer(s);
113         }
114
115         while (readCount < packet->packetLength)
116         {
117                 status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), packet->packetLength - readCount);
118
119                 if (status < 0)
120                 {
121                         continue;
122                 }
123
124                 readCount += status;
125                 Stream_Seek(s, readCount);
126         }
127
128         Stream_SealLength(s);
129
130         return s;
131 }
132
133 BOOL rdg_send_handshake(rdpRdg* rdg)
134 {
135         wStream* s;
136         BOOL status;
137
138         s = Stream_New(NULL, 14);
139
140         if (!s)
141                 return FALSE;
142
143         Stream_Write_UINT16(s, PKT_TYPE_HANDSHAKE_REQUEST); /* Type (2 bytes) */
144         Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
145         Stream_Write_UINT32(s, 14); /* PacketLength (4 bytes) */
146
147         Stream_Write_UINT8(s, 1); /* VersionMajor (1 byte) */
148         Stream_Write_UINT8(s, 0); /* VersionMinor (1 byte) */
149         Stream_Write_UINT16(s, 0); /* ClientVersion (2 bytes), must be 0 */
150         Stream_Write_UINT16(s, 0); /* ExtendedAuthentication (2 bytes) */
151
152         Stream_SealLength(s);
153
154         status = rdg_write_packet(rdg, s);
155         Stream_Free(s, TRUE);
156
157         if (status)
158         {
159                 rdg->state = RDG_CLIENT_STATE_HANDSHAKE;
160         }
161
162         return status;
163 }
164
165 BOOL rdg_send_tunnel_request(rdpRdg* rdg)
166 {
167         wStream* s;
168         BOOL status;
169
170         s = Stream_New(NULL, 16);
171
172         if (!s)
173                 return FALSE;
174
175         Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_CREATE); /* Type (2 bytes) */
176         Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
177         Stream_Write_UINT32(s, 16); /* PacketLength (4 bytes) */
178
179         Stream_Write_UINT32(s, HTTP_CAPABILITY_TYPE_QUAR_SOH); /* CapabilityFlags (4 bytes) */
180         Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */
181         Stream_Write_UINT16(s, 0); /* Reserved (2 bytes), must be 0 */
182
183         Stream_SealLength(s);
184
185         status = rdg_write_packet(rdg, s);
186         Stream_Free(s, TRUE);
187
188         if (status)
189         {
190                 rdg->state = RDG_CLIENT_STATE_TUNNEL_CREATE;
191         }
192
193         return status;
194 }
195
196 BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
197 {
198         int i;
199         wStream* s;
200         BOOL status;
201         char* clientName = rdg->settings->ClientHostname;
202         UINT16 clientNameLen = strlen(clientName) + 1;
203         UINT32 packetSize = 12 + clientNameLen * 2;
204
205         s = Stream_New(NULL, packetSize);
206
207         if (!s)
208                 return FALSE;
209
210         Stream_Write_UINT16(s, PKT_TYPE_TUNNEL_AUTH); /* Type (2 bytes) */
211         Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
212         Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
213
214         Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */
215         Stream_Write_UINT16(s, clientNameLen * 2); /* Client name string length */
216
217         for (i = 0; i < clientNameLen; i++)
218         {
219                 Stream_Write_UINT16(s, clientName[i]);
220         }
221
222         Stream_SealLength(s);
223
224         status = rdg_write_packet(rdg, s);
225
226         Stream_Free(s, TRUE);
227
228         if (status)
229         {
230                 rdg->state = RDG_CLIENT_STATE_TUNNEL_AUTHORIZE;
231         }
232
233         return status;
234 }
235
236 BOOL rdg_send_channel_create(rdpRdg* rdg)
237 {
238         int i;
239         wStream* s;
240         BOOL status;
241         char* serverName = rdg->settings->ServerHostname;
242         UINT16 serverNameLen = strlen(serverName) + 1;
243         UINT32 packetSize = 16 + serverNameLen * 2;
244
245         s = Stream_New(NULL, packetSize);
246
247         if (!s)
248                 return FALSE;
249
250         Stream_Write_UINT16(s, PKT_TYPE_CHANNEL_CREATE); /* Type (2 bytes) */
251         Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
252         Stream_Write_UINT32(s, packetSize); /* PacketLength (4 bytes) */
253
254         Stream_Write_UINT8(s, 1); /* Number of resources. (1 byte) */
255         Stream_Write_UINT8(s, 0); /* Number of alternative resources (1 byte) */
256         Stream_Write_UINT16(s, rdg->settings->ServerPort); /* Resource port (2 bytes) */
257         Stream_Write_UINT16(s, 3); /* Protocol number (2 bytes) */
258         Stream_Write_UINT16(s, serverNameLen * 2);
259
260         for (i = 0; i < serverNameLen; i++)
261         {
262                 Stream_Write_UINT16(s, serverName[i]);
263         }
264
265         Stream_SealLength(s);
266
267         status = rdg_write_packet(rdg, s);
268
269         Stream_Free(s, TRUE);
270
271         if (status)
272         {
273                 rdg->state = RDG_CLIENT_STATE_CHANNEL_CREATE;
274         }
275
276         return status;
277 }
278
279 wStream* rdg_build_http_request(rdpRdg* rdg, char* method)
280 {
281         wStream* s;
282         HttpRequest* request = NULL;
283         SecBuffer* ntlmToken = NULL;
284         char* base64NtlmToken = NULL;
285
286         assert(method != NULL);
287
288         request = http_request_new();
289
290         if (!request)
291                 return NULL;
292
293         http_request_set_method(request, method);
294         http_request_set_uri(request, rdg->http->URI);
295
296         if (!request->Method || !request->URI)
297                 return NULL;
298
299         if (rdg->ntlm)
300         {
301                 ntlmToken = rdg->ntlm->outputBuffer;
302
303                 if (ntlmToken)
304                         base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);
305
306                 if (base64NtlmToken)
307                 {
308                         http_request_set_auth_scheme(request, "NTLM");
309                         http_request_set_auth_param(request, base64NtlmToken);
310
311                         free(base64NtlmToken);
312
313                         if (!request->AuthScheme || !request->AuthParam)
314                                 return NULL;
315                 }
316         }
317
318         if (rdg->state == RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED)
319         {
320                 http_request_set_transfer_encoding(request, "chunked");
321         }
322
323         s = http_request_write(rdg->http, request);
324         http_request_free(request);
325
326         if (s)
327                 Stream_SealLength(s);
328         return s;
329 }
330
331 BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response)
332 {
333         int status;
334         wStream* s;
335         char* token64 = NULL;
336         int ntlmTokenLength = 0;
337         BYTE* ntlmTokenData = NULL;
338         rdpNtlm* ntlm = rdg->ntlm;
339
340         if (response->StatusCode != HTTP_STATUS_DENIED)
341         {
342                 WLog_DBG(TAG, "RDG not supported");
343                 rdg->state = RDG_CLIENT_STATE_NOT_FOUND;
344                 return FALSE;
345         }
346
347         WLog_DBG(TAG, "Out Channel authorization required");
348
349         if (ListDictionary_Contains(response->Authenticates, "NTLM"))
350         {
351                 token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
352
353                 if (!token64)
354                 {
355                         return FALSE;
356                 }
357
358                 crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
359         }
360
361         if (ntlmTokenData && ntlmTokenLength)
362         {
363                 ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
364                 ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
365         }
366
367         ntlm_authenticate(ntlm);
368
369         s = rdg_build_http_request(rdg, "RDG_OUT_DATA");
370
371         if (!s)
372                 return FALSE;
373
374         status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s));
375
376         Stream_Free(s, TRUE);
377
378         ntlm_free(rdg->ntlm);
379         rdg->ntlm = NULL;
380
381         if (status < 0)
382         {
383                 return FALSE;
384         }
385
386         rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE;
387
388         return TRUE;
389 }
390
391 BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response)
392 {
393         if (response->StatusCode != HTTP_STATUS_OK)
394         {
395                 rdg->state = RDG_CLIENT_STATE_CLOSED;
396                 return FALSE;
397         }
398
399         WLog_DBG(TAG, "Out Channel authorization complete");
400         rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED;
401
402         return TRUE;
403 }
404
405 BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response)
406 {
407         int status;
408         wStream* s;
409         char* token64 = NULL;
410         int ntlmTokenLength = 0;
411         BYTE* ntlmTokenData = NULL;
412         rdpNtlm* ntlm = rdg->ntlm;
413
414         WLog_DBG(TAG, "In Channel authorization required");
415
416         if (ListDictionary_Contains(response->Authenticates, "NTLM"))
417         {
418                 token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
419
420                 if (!token64)
421                 {
422                         return FALSE;
423                 }
424
425                 crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
426         }
427
428         if (ntlmTokenData && ntlmTokenLength)
429         {
430                 ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
431                 ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
432         }
433
434         ntlm_authenticate(ntlm);
435
436         s = rdg_build_http_request(rdg, "RDG_IN_DATA");
437
438         if (!s)
439                 return FALSE;
440
441         status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
442
443         Stream_Free(s, TRUE);
444
445         ntlm_free(rdg->ntlm);
446         rdg->ntlm = NULL;
447
448         if (status < 0)
449         {
450                 return FALSE;
451         }
452
453         rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE;
454
455         return TRUE;
456 }
457
458 BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response)
459 {
460         wStream* s;
461         int status;
462
463         if (response->StatusCode != HTTP_STATUS_OK)
464         {
465                 rdg->state = RDG_CLIENT_STATE_CLOSED;
466                 return FALSE;
467         }
468
469         WLog_DBG(TAG, "In Channel authorization complete");
470         rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED;
471
472         s = rdg_build_http_request(rdg, "RDG_IN_DATA");
473
474         if (!s)
475                 return FALSE;
476
477         status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
478     if (status <= 0)
479     {
480         return FALSE;
481     }
482         Stream_Free(s, TRUE);
483
484         return TRUE;
485 }
486
487 BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
488 {
489         HRESULT errorCode;
490
491         WLog_DBG(TAG, "Handshake response received");
492
493         if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
494         {
495                 return FALSE;
496         }
497
498         if (Stream_GetRemainingLength(s) < 12)
499                 return FALSE;
500
501         Stream_Seek(s, 8);
502         Stream_Read_UINT32(s, errorCode);
503
504         if (FAILED(errorCode))
505         {
506                 WLog_DBG(TAG, "Handshake error %x", errorCode);
507                 return FALSE;
508         }
509
510         return rdg_send_tunnel_request(rdg);
511 }
512
513 BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
514 {
515         HRESULT errorCode;
516
517         WLog_DBG(TAG, "Tunnel response received");
518
519         if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
520         {
521                 return FALSE;
522         }
523
524         if (Stream_GetRemainingLength(s) < 14)
525                 return FALSE;
526
527         Stream_Seek(s, 10);
528         Stream_Read_UINT32(s, errorCode);
529
530         if (FAILED(errorCode))
531         {
532                 WLog_DBG(TAG, "Tunnel creation error %x", errorCode);
533                 return FALSE;
534         }
535
536         return rdg_send_tunnel_authorization(rdg);
537 }
538
539 BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
540 {
541         HRESULT errorCode;
542
543         WLog_DBG(TAG, "Tunnel authorization received");
544
545         if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
546         {
547                 return FALSE;
548         }
549
550         if (Stream_GetRemainingLength(s) < 12)
551                 return FALSE;
552
553         Stream_Seek(s, 8);
554         Stream_Read_UINT32(s, errorCode);
555
556         if (FAILED(errorCode))
557         {
558                 WLog_DBG(TAG, "Tunnel authorization error %x", errorCode);
559                 return FALSE;
560         }
561
562         return rdg_send_channel_create(rdg);
563 }
564
565 BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
566 {
567         HRESULT errorCode;
568
569         WLog_DBG(TAG, "Channel response received");
570
571         if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
572         {
573                 return FALSE;
574         }
575
576         if (Stream_GetRemainingLength(s) < 12)
577                 return FALSE;
578
579         Stream_Seek(s, 8);
580         Stream_Read_UINT32(s, errorCode);
581
582         if (FAILED(errorCode))
583         {
584                 WLog_DBG(TAG, "Channel error %x", errorCode);
585                 return FALSE;
586         }
587
588         rdg->state = RDG_CLIENT_STATE_OPENED;
589
590         return TRUE;
591 }
592
593 BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
594 {
595         BOOL status = TRUE;
596         UINT16 type;
597
598         Stream_SetPosition(s, 0);
599
600         if (Stream_GetRemainingLength(s) < 2)
601                 return FALSE;
602
603         Stream_Peek_UINT16(s, type);
604
605         switch (type)
606         {
607                 case PKT_TYPE_HANDSHAKE_RESPONSE:
608                         status = rdg_process_handshake_response(rdg, s);
609                         break;
610
611                 case PKT_TYPE_TUNNEL_RESPONSE:
612                         status = rdg_process_tunnel_response(rdg, s);
613                         break;
614
615                 case PKT_TYPE_TUNNEL_AUTH_RESPONSE:
616                         status = rdg_process_tunnel_authorization_response(rdg, s);
617                         break;
618
619                 case PKT_TYPE_CHANNEL_RESPONSE:
620                         status = rdg_process_channel_response(rdg, s);
621                         break;
622
623                 case PKT_TYPE_DATA:
624                         assert(FALSE);
625                         return FALSE;
626         }
627
628         return status;
629 }
630
631
632 BOOL rdg_out_channel_recv(rdpRdg* rdg)
633 {
634         wStream* s;
635         BOOL status = TRUE;
636         HttpResponse* response = NULL;
637
638         switch (rdg->state)
639         {
640                 case RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST:
641                         response = http_response_recv(rdg->tlsOut);
642                         if (!response)
643                         {
644                                 return FALSE;
645                         }
646                         status = rdg_process_out_channel_response(rdg, response);
647                         http_response_free(response);
648                         break;
649
650                 case RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE:
651                         response = http_response_recv(rdg->tlsOut);
652                         if (!response)
653                         {
654                                 return FALSE;
655                         }
656                         status = rdg_process_out_channel_authorization(rdg, response);
657                         http_response_free(response);
658                         break;
659
660                 default:
661                         s = rdg_receive_packet(rdg);
662                         if (s)
663                         {
664                                 status = rdg_process_packet(rdg, s);
665                                 Stream_Free(s, TRUE);
666                         }
667         }
668
669         return status;
670 }
671
672 BOOL rdg_in_channel_recv(rdpRdg* rdg)
673 {
674         BOOL status = TRUE;
675         HttpResponse* response = NULL;
676
677         switch (rdg->state)
678         {
679                 case RDG_CLIENT_STATE_IN_CHANNEL_REQUEST:
680                         response = http_response_recv(rdg->tlsIn);
681
682                         if (!response)
683                                 return FALSE;
684
685                         status = rdg_process_in_channel_response(rdg, response);
686                         http_response_free(response);
687                         break;
688
689                 case RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE:
690                         response = http_response_recv(rdg->tlsIn);
691
692                         if (!response)
693                                 return FALSE;
694
695                         status = rdg_process_in_channel_authorization(rdg, response);
696                         http_response_free(response);
697                         break;
698         }
699
700         return status;
701 }
702
703 DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count)
704 {
705         DWORD nCount = 0;
706
707         assert(rdg != NULL);
708
709         if (events && (nCount < count))
710                 events[nCount++] = rdg->readEvent;
711         else
712                 return 0;
713
714         if (rdg->tlsOut && rdg->tlsOut->bio)
715         {
716                 if (events && (nCount < count))
717                 {
718                         BIO_get_event(rdg->tlsOut->bio, &events[nCount]);
719                         nCount++;
720                 }
721                 else
722                         return 0;
723         }
724
725         if (rdg->tlsIn && rdg->tlsIn->bio)
726         {
727                 if (events && (nCount < count))
728                 {
729                         BIO_get_event(rdg->tlsIn->bio, &events[nCount]);
730                         nCount++;
731                 }
732                 else
733                         return 0;
734         }
735
736         return nCount;
737 }
738
739 BOOL rdg_check_event_handles(rdpRdg* rdg)
740 {
741         HANDLE event = NULL;
742
743         assert(rdg != NULL);
744
745         BIO_get_event(rdg->tlsOut->bio, &event);
746
747         if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
748         {
749                 return rdg_out_channel_recv(rdg);
750         }
751
752         BIO_get_event(rdg->tlsIn->bio, &event);
753
754         if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
755         {
756                 return rdg_in_channel_recv(rdg);
757         }
758
759         return TRUE;
760 }
761
762 BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls)
763 {
764         rdpNtlm* ntlm = rdg->ntlm;
765         rdpContext* context = rdg->context;
766         rdpSettings* settings = context->settings;
767         freerdp* instance = context->instance;
768
769         if (!settings->GatewayPassword || !settings->GatewayUsername || !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername))
770         {
771                 if (instance->GatewayAuthenticate)
772                 {
773                         BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain);
774
775                         if (!proceed)
776                         {
777                                 freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
778                                 return FALSE;
779                         }
780
781                         if (settings->GatewayUseSameCredentials)
782                         {
783                                 if (settings->GatewayUsername)
784                                 {
785                                         free(settings->Username);
786                                         if (!(settings->Username = _strdup(settings->GatewayUsername)))
787                                                 return FALSE;
788                                 }
789                                 if (settings->GatewayDomain)
790                                 {
791                                         free(settings->Domain);
792                                         if (!(settings->Domain = _strdup(settings->GatewayDomain)))
793                                                 return FALSE;
794                                 }
795                                 if (settings->GatewayPassword)
796                                 {
797                                         free(settings->Password);
798                                         if (!(settings->Password = _strdup(settings->GatewayPassword)))
799                                                 return FALSE;
800                                 }
801                         }
802                 }
803         }
804
805         if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, tls->Bindings))
806         {
807                 return FALSE;
808         }
809
810         if (!ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname))
811         {
812                 return FALSE;
813         }
814
815         return TRUE;
816 }
817
818 BOOL rdg_send_out_channel_request(rdpRdg*rdg)
819 {
820         wStream* s = NULL;
821         int status;
822
823         rdg->ntlm = ntlm_new();
824
825         if (!rdg->ntlm)
826                 return FALSE;
827
828         status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsOut);
829
830         if (!status)
831                 return FALSE;
832
833         status = ntlm_authenticate(rdg->ntlm);
834
835         if (!status)
836                 return FALSE;
837
838         s = rdg_build_http_request(rdg, "RDG_OUT_DATA");
839
840         if (!s)
841                 return FALSE;
842
843         status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s));
844
845         Stream_Free(s, TRUE);
846
847         if (status < 0)
848                 return FALSE;
849
850         rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST;
851
852         return TRUE;
853 }
854
855 BOOL rdg_send_in_channel_request(rdpRdg*rdg)
856 {
857         int status;
858         wStream* s = NULL;
859
860         rdg->ntlm = ntlm_new();
861
862         if (!rdg->ntlm)
863                 return FALSE;
864
865         status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsIn);
866
867         if (!status)
868                 return FALSE;
869
870         status = ntlm_authenticate(rdg->ntlm);
871
872         if (!status)
873                 return FALSE;
874
875         s = rdg_build_http_request(rdg, "RDG_IN_DATA");
876
877         if (!s)
878                 return FALSE;
879
880         status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
881
882         Stream_Free(s, TRUE);
883
884         if (status < 0)
885                 return FALSE;
886
887         rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_REQUEST;
888
889         return TRUE;
890 }
891
892 BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
893 {
894         int sockfd = 0;
895         int status = 0;
896         BIO* socketBio = NULL;
897         BIO* bufferedBio = NULL;
898         rdpSettings* settings = rdg->settings;
899
900         assert(hostname != NULL);
901
902         sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
903
904         if (sockfd < 1)
905         {
906                 return FALSE;
907         }
908
909         socketBio = BIO_new(BIO_s_simple_socket());
910
911         if (!socketBio)
912         {
913                 closesocket(sockfd);
914                 return FALSE;
915         }
916
917         BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
918         bufferedBio = BIO_new(BIO_s_buffered_socket());
919
920         if (!bufferedBio)
921         {
922                 BIO_free(socketBio);
923                 return FALSE;
924         }
925
926         bufferedBio = BIO_push(bufferedBio, socketBio);
927         status = BIO_set_nonblock(bufferedBio, TRUE);
928
929         if (!status)
930         {
931                 BIO_free_all(bufferedBio);
932                 return FALSE;
933         }
934
935         rdg->tlsOut->hostname = settings->GatewayHostname;
936         rdg->tlsOut->port = settings->GatewayPort;
937         rdg->tlsOut->isGatewayTransport = TRUE;
938         status = tls_connect(rdg->tlsOut, bufferedBio);
939
940         if (status < 1)
941         {
942                 return FALSE;
943         }
944
945         return TRUE;
946 }
947
948 BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
949 {
950         int sockfd = 0;
951         int status = 0;
952         BIO* socketBio = NULL;
953         BIO* bufferedBio = NULL;
954         rdpSettings* settings = rdg->settings;
955
956         assert(hostname != NULL);
957
958         sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
959
960         if (sockfd < 1)
961                 return FALSE;
962
963         socketBio = BIO_new(BIO_s_simple_socket());
964
965         if (!socketBio)
966         {
967                 closesocket(sockfd);
968                 return FALSE;
969         }
970
971         BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
972         bufferedBio = BIO_new(BIO_s_buffered_socket());
973
974         if (!bufferedBio)
975         {
976                 BIO_free(socketBio);
977                 return FALSE;
978         }
979
980         bufferedBio = BIO_push(bufferedBio, socketBio);
981         status = BIO_set_nonblock(bufferedBio, TRUE);
982
983         if (!status)
984         {
985                 BIO_free_all(bufferedBio);
986                 return FALSE;
987         }
988
989         rdg->tlsIn->hostname = settings->GatewayHostname;
990         rdg->tlsIn->port = settings->GatewayPort;
991         rdg->tlsIn->isGatewayTransport = TRUE;
992         status = tls_connect(rdg->tlsIn, bufferedBio);
993
994         if (status < 1)
995         {
996                 return FALSE;
997         }
998
999         return TRUE;
1000 }
1001
1002 BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1003 {
1004         BOOL status;
1005         DWORD nCount;
1006         HANDLE events[8];
1007
1008         assert(hostname != NULL);
1009
1010         status = rdg_tls_out_connect(rdg, hostname, port, timeout);
1011
1012         if (!status)
1013                 return FALSE;
1014
1015         status = rdg_send_out_channel_request(rdg);
1016
1017         if (!status)
1018                 return FALSE;
1019
1020         nCount = rdg_get_event_handles(rdg, events, 8);
1021
1022         if (nCount == 0)
1023                 return FALSE;
1024
1025         while (rdg->state <= RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE)
1026         {
1027                 WaitForMultipleObjects(nCount, events, FALSE, 100);
1028                 status = rdg_check_event_handles(rdg);
1029
1030                 if (!status)
1031                 {
1032                         rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1033                         return FALSE;
1034                 }
1035         }
1036
1037         return TRUE;
1038 }
1039
1040 BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1041 {
1042         BOOL status;
1043         DWORD nCount;
1044         HANDLE events[8];
1045
1046         assert(hostname != NULL);
1047
1048         status = rdg_tls_in_connect(rdg, hostname, port, timeout);
1049
1050         if (!status)
1051                 return FALSE;
1052
1053         status = rdg_send_in_channel_request(rdg);
1054
1055         if (!status)
1056                 return FALSE;
1057
1058         nCount = rdg_get_event_handles(rdg, events, 8);
1059
1060         if (nCount == 0)
1061                 return FALSE;
1062
1063         while (rdg->state <= RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE)
1064         {
1065                 WaitForMultipleObjects(nCount, events, FALSE, 100);
1066                 status = rdg_check_event_handles(rdg);
1067
1068                 if (!status)
1069                 {
1070                         rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1071                         return FALSE;
1072                 }
1073         }
1074
1075         return TRUE;
1076 }
1077
1078 BOOL rdg_tunnel_connect(rdpRdg* rdg)
1079 {
1080         BOOL status;
1081         DWORD nCount;
1082         HANDLE events[8];
1083
1084         rdg_send_handshake(rdg);
1085
1086         nCount = rdg_get_event_handles(rdg, events, 8);
1087
1088         if (nCount == 0)
1089                 return FALSE;
1090
1091         while (rdg->state < RDG_CLIENT_STATE_OPENED)
1092         {
1093                 WaitForMultipleObjects(nCount, events, FALSE, 100);
1094                 status = rdg_check_event_handles(rdg);
1095
1096                 if (!status)
1097                 {
1098                         rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1099                         return FALSE;
1100                 }
1101         }
1102
1103         return TRUE;
1104 }
1105
1106 BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1107 {
1108         BOOL status;
1109
1110         assert(rdg != NULL);
1111
1112         status = rdg_out_channel_connect(rdg, hostname, port, timeout);
1113
1114         if (!status)
1115                 return FALSE;
1116
1117         status = rdg_in_channel_connect(rdg, hostname, port, timeout);
1118
1119         if (!status)
1120                 return FALSE;
1121
1122         status = rdg_tunnel_connect(rdg);
1123
1124         if (!status)
1125                 return FALSE;
1126
1127         return TRUE;
1128 }
1129
1130 int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
1131 {
1132         int status;
1133         wStream* sChunk;
1134         int packetSize = size + 10;
1135         char chunkSize[11];
1136
1137         if (size < 1)
1138                 return 0;
1139
1140         sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1141
1142         sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1143
1144         if (!sChunk)
1145                 return -1;
1146
1147         Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1148
1149         Stream_Write_UINT16(sChunk, PKT_TYPE_DATA);   /* Type */
1150         Stream_Write_UINT16(sChunk, 0);   /* Reserved */
1151         Stream_Write_UINT32(sChunk, packetSize);   /* Packet length */
1152
1153         Stream_Write_UINT16(sChunk, size);   /* Data size */
1154         Stream_Write(sChunk, buf, size);   /* Data */
1155
1156         Stream_Write(sChunk, "\r\n", 2);
1157         Stream_SealLength(sChunk);
1158
1159         status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1160         Stream_Free(sChunk, TRUE);
1161
1162         if (status < 0)
1163                 return -1;
1164
1165         return size;
1166 }
1167
1168 BOOL rdg_process_close_packet(rdpRdg* rdg)
1169 {
1170     int status;
1171     wStream* sChunk;
1172     int packetSize = 12;
1173     char chunkSize[11];
1174     
1175     sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1176     
1177     sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1178     
1179     if (!sChunk)
1180         return FALSE;
1181     
1182     Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1183     
1184     Stream_Write_UINT16(sChunk, PKT_TYPE_CLOSE_CHANNEL_RESPONSE);   /* Type */
1185     Stream_Write_UINT16(sChunk, 0);   /* Reserved */
1186     Stream_Write_UINT32(sChunk, packetSize);   /* Packet length */
1187     
1188     Stream_Write_UINT32(sChunk, 0);   /* Status code */
1189     
1190     Stream_Write(sChunk, "\r\n", 2);
1191     Stream_SealLength(sChunk);
1192     
1193     status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1194     Stream_Free(sChunk, TRUE);
1195     
1196     return (status < 0 ? FALSE : TRUE);
1197 }
1198
1199 BOOL rdg_process_keep_alive_packet(rdpRdg* rdg)
1200 {
1201     int status;
1202     wStream* sChunk;
1203     int packetSize = 8;
1204     char chunkSize[11];
1205     
1206     sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1207     
1208     sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1209     
1210     if (!sChunk)
1211         return FALSE;
1212     
1213     Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1214     
1215     Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE);   /* Type */
1216     Stream_Write_UINT16(sChunk, 0);   /* Reserved */
1217     Stream_Write_UINT32(sChunk, packetSize);   /* Packet length */
1218     
1219     Stream_Write(sChunk, "\r\n", 2);
1220     Stream_SealLength(sChunk);
1221     
1222     status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1223     Stream_Free(sChunk, TRUE);
1224     
1225     return (status < 0 ? FALSE : TRUE);
1226 }
1227
1228 BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
1229 {
1230         WLog_WARN(TAG, "Unknown Control Packet received: %X", type);
1231
1232         return TRUE;
1233 }
1234
1235 BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength)
1236 {
1237         wStream* s = NULL;
1238         int readCount = 0;
1239         int status;
1240         int payloadSize = packetLength - sizeof(RdgPacketHeader);
1241
1242         if (payloadSize)
1243         {
1244                 s = Stream_New(NULL, payloadSize);
1245                 if (!s)
1246                 {
1247                         return FALSE;
1248                 }
1249
1250                 while (readCount < payloadSize)
1251                 {
1252                         status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);
1253
1254                         if (status <= 0)
1255                         {
1256                                 if (!BIO_should_retry(rdg->tlsOut->bio))
1257                                 {
1258                                         Stream_Free(s, TRUE);
1259                                         return FALSE;
1260                                 }
1261                                 continue;
1262                         }
1263
1264                         Stream_Seek(s, status);
1265                         readCount += status;
1266                 }
1267         }
1268
1269         switch (type)
1270         {
1271         case PKT_TYPE_CLOSE_CHANNEL:
1272         EnterCriticalSection(&rdg->writeSection);
1273                 status = rdg_process_close_packet(rdg);
1274         LeaveCriticalSection(&rdg->writeSection);
1275         break;
1276
1277     case PKT_TYPE_KEEPALIVE:
1278         EnterCriticalSection(&rdg->writeSection);
1279         status = rdg_process_keep_alive_packet(rdg);
1280         LeaveCriticalSection(&rdg->writeSection);
1281         break;
1282             
1283         default:
1284                 status = rdg_process_unknown_packet(rdg, type);
1285                 break;
1286         }
1287
1288         Stream_Free(s, TRUE);
1289
1290         return status;
1291 }
1292
1293 int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
1294 {
1295         RdgPacketHeader header;
1296         int readCount = 0;
1297         int readSize;
1298         int status;
1299         int pending;
1300
1301         if (!rdg->packetRemainingCount)
1302         {
1303                 while (readCount < sizeof(RdgPacketHeader))
1304                 {
1305                         status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, sizeof(RdgPacketHeader) - readCount);
1306
1307                         if (status <= 0)
1308                         {
1309                                 if (!BIO_should_retry(rdg->tlsOut->bio))
1310                                 {
1311                                         return -1;
1312                                 }
1313                                 if (!readCount)
1314                                 {
1315                                         return 0;
1316                                 }
1317                                 continue;
1318                         }
1319
1320                         readCount += status;
1321                 }
1322
1323                 if (header.type != PKT_TYPE_DATA)
1324                 {
1325                         status = rdg_process_control_packet(rdg, header.type, header.packetLength);
1326                         if (!status)
1327                         {
1328                                 return -1;
1329                         }
1330                         return 0;
1331                 }
1332
1333                 readCount = 0;
1334
1335                 while (readCount < 2)
1336                 {
1337                         status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, 2 - readCount);
1338
1339                         if (status < 0)
1340                         {
1341                                 if (!BIO_should_retry(rdg->tlsOut->bio))
1342                                 {
1343                                         return -1;
1344                                 }
1345                                 continue;
1346                         }
1347
1348                         readCount += status;
1349                 }
1350         }
1351
1352         readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size);
1353
1354         status = BIO_read(rdg->tlsOut->bio, buffer, readSize);
1355
1356         if (status <= 0)
1357         {
1358                 if (!BIO_should_retry(rdg->tlsOut->bio))
1359                 {
1360                         return -1;
1361                 }
1362         return 0;
1363         }
1364
1365         rdg->packetRemainingCount -= status;
1366
1367         pending = BIO_pending(rdg->tlsOut->bio);
1368
1369         if (pending > 0)
1370                 SetEvent(rdg->readEvent);
1371         else
1372                 ResetEvent(rdg->readEvent);
1373
1374         return status;
1375 }
1376
1377 long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
1378 {
1379         return 1;
1380 }
1381
1382 static int rdg_bio_write(BIO* bio, const char* buf, int num)
1383 {
1384         int status;
1385         rdpRdg* rdg = (rdpRdg*)bio->ptr;
1386
1387         BIO_clear_flags(bio, BIO_FLAGS_WRITE);
1388
1389     EnterCriticalSection(&rdg->writeSection);
1390         status = rdg_write_data_packet(rdg, (BYTE*) buf, num);
1391     LeaveCriticalSection(&rdg->writeSection);
1392
1393         if (status < 0)
1394         {
1395                 BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
1396                 return -1;
1397         }
1398         else if (status < num)
1399         {
1400                 BIO_set_flags(bio, BIO_FLAGS_WRITE);
1401                 WSASetLastError(WSAEWOULDBLOCK);
1402         }
1403         else
1404         {
1405                 BIO_clear_flags(bio, BIO_FLAGS_WRITE);
1406         }
1407
1408         return status;
1409 }
1410
1411 static int rdg_bio_read(BIO* bio, char* buf, int size)
1412 {
1413         int status;
1414         rdpRdg* rdg = (rdpRdg*)bio->ptr;
1415
1416         status = rdg_read_data_packet(rdg, (BYTE*) buf, size);
1417
1418     if (!status)
1419     {
1420         BIO_set_retry_read(bio);
1421         return -1;
1422     }
1423         else if (status < 0)
1424         {
1425         BIO_clear_retry_flags(bio);
1426                 return -1;
1427         }
1428
1429         return status;
1430 }
1431
1432 static int rdg_bio_puts(BIO* bio, const char* str)
1433 {
1434         return -2;
1435 }
1436
1437 static int rdg_bio_gets(BIO* bio, char* str, int size)
1438 {
1439         return -2;
1440 }
1441
1442 static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
1443 {
1444         int status = 0;
1445         rdpRdg* rdg = (rdpRdg*)bio->ptr;
1446         rdpTls* tlsOut = rdg->tlsOut;
1447         rdpTls* tlsIn = rdg->tlsIn;
1448
1449         if (cmd == BIO_CTRL_FLUSH)
1450         {
1451                 (void)BIO_flush(tlsOut->bio);
1452                 (void)BIO_flush(tlsIn->bio);
1453                 status = 1;
1454         }
1455         else if (cmd == BIO_C_GET_EVENT)
1456         {
1457                 if (arg2)
1458                 {
1459                         BIO_get_event(rdg->tlsOut->bio, arg2);
1460                         status = 1;
1461                 }
1462         }
1463         else if (cmd == BIO_C_SET_NONBLOCK)
1464         {
1465                 status = 1;
1466         }
1467         else if (cmd == BIO_C_READ_BLOCKED)
1468         {
1469                 status = 0;
1470         }
1471         else if (cmd == BIO_C_WRITE_BLOCKED)
1472         {
1473                 status = 0;
1474         }
1475         else if (cmd == BIO_C_WAIT_READ)
1476         {
1477                 int timeout = (int)arg1;
1478                 return BIO_wait_read(tlsOut->bio, timeout);
1479         }
1480         else if (cmd == BIO_C_WAIT_WRITE)
1481         {
1482                 status = 0;
1483         }
1484
1485         return status;
1486 }
1487
1488 static int rdg_bio_new(BIO* bio)
1489 {
1490         bio->init = 1;
1491         bio->num = 0;
1492         bio->ptr = NULL;
1493         bio->flags = BIO_FLAGS_SHOULD_RETRY;
1494         return 1;
1495 }
1496
1497 static int rdg_bio_free(BIO* bio)
1498 {
1499         return 1;
1500 }
1501
1502 static BIO_METHOD rdg_bio_methods =
1503 {
1504         BIO_TYPE_TSG,
1505         "RDGateway",
1506         rdg_bio_write,
1507         rdg_bio_read,
1508         rdg_bio_puts,
1509         rdg_bio_gets,
1510         rdg_bio_ctrl,
1511         rdg_bio_new,
1512         rdg_bio_free,
1513         NULL,
1514 };
1515
1516 BIO_METHOD* BIO_s_rdg(void)
1517 {
1518         return &rdg_bio_methods;
1519 }
1520
1521 rdpRdg* rdg_new(rdpTransport* transport)
1522 {
1523         rdpRdg* rdg;
1524         RPC_CSTR stringUuid;
1525         char bracedUuid[40];
1526         RPC_STATUS rpcStatus;
1527
1528         assert(transport != NULL);
1529
1530         rdg = (rdpRdg*) calloc(1, sizeof(rdpRdg));
1531
1532         if (rdg)
1533         {
1534                 rdg->state = RDG_CLIENT_STATE_INITIAL;
1535                 rdg->context = transport->context;
1536                 rdg->settings = rdg->context->settings;
1537
1538                 UuidCreate(&rdg->guid);
1539
1540                 rpcStatus = UuidToStringA(&rdg->guid, &stringUuid);
1541
1542                 if (rpcStatus == RPC_S_OUT_OF_MEMORY)
1543                         goto rdg_alloc_error;
1544
1545                 sprintf_s(bracedUuid, sizeof(bracedUuid), "{%s}", stringUuid);
1546                 RpcStringFreeA(&stringUuid);
1547
1548                 rdg->tlsOut = tls_new(rdg->settings);
1549
1550                 if (!rdg->tlsOut)
1551                         goto rdg_alloc_error;
1552
1553                 rdg->tlsIn = tls_new(rdg->settings);
1554
1555                 if (!rdg->tlsIn)
1556                         goto rdg_alloc_error;
1557
1558                 rdg->http = http_context_new();
1559
1560                 if (!rdg->http)
1561                         goto rdg_alloc_error;
1562
1563                 http_context_set_uri(rdg->http, "/remoteDesktopGateway/");
1564                 http_context_set_accept(rdg->http, "*/*");
1565                 http_context_set_cache_control(rdg->http, "no-cache");
1566                 http_context_set_pragma(rdg->http, "no-cache");
1567                 http_context_set_connection(rdg->http, "Keep-Alive");
1568                 http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0");
1569                 http_context_set_host(rdg->http, rdg->settings->GatewayHostname);
1570                 http_context_set_rdg_connection_id(rdg->http, bracedUuid);
1571
1572                 if (!rdg->http->URI || !rdg->http->Accept || !rdg->http->CacheControl ||
1573                                 !rdg->http->Pragma || !rdg->http->Connection || !rdg->http->UserAgent
1574                                 || !rdg->http->Host || !rdg->http->RdgConnectionId)
1575                 {
1576                         goto rdg_alloc_error;
1577                 }
1578
1579                 rdg->frontBio = BIO_new(BIO_s_rdg());
1580
1581                 if (!rdg->frontBio)
1582                         goto rdg_alloc_error;
1583
1584                 rdg->frontBio->ptr = rdg;
1585
1586                 rdg->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1587
1588                 if (!rdg->readEvent)
1589                         goto rdg_alloc_error;
1590         
1591         InitializeCriticalSection(&rdg->writeSection);
1592         }
1593
1594         return rdg;
1595
1596 rdg_alloc_error:
1597         rdg_free(rdg);
1598         return NULL;
1599 }
1600
1601 void rdg_free(rdpRdg* rdg)
1602 {
1603         if (!rdg)
1604                 return;
1605
1606         if (rdg->tlsOut)
1607         {
1608                 tls_free(rdg->tlsOut);
1609                 rdg->tlsOut = NULL;
1610         }
1611
1612         if (rdg->tlsIn)
1613         {
1614                 tls_free(rdg->tlsIn);
1615                 rdg->tlsIn = NULL;
1616         }
1617
1618         if (rdg->http)
1619         {
1620                 http_context_free(rdg->http);
1621                 rdg->http = NULL;
1622         }
1623
1624         if (rdg->ntlm)
1625         {
1626                 ntlm_free(rdg->ntlm);
1627                 rdg->ntlm = NULL;
1628         }
1629
1630         if (rdg->readEvent)
1631         {
1632                 CloseHandle(rdg->readEvent);
1633                 rdg->readEvent = NULL;
1634         }
1635     
1636     DeleteCriticalSection(&rdg->writeSection);
1637
1638         free(rdg);
1639 }