libfreerdp-core: fix code style
[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
329         return s;
330 }
331
332 BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response)
333 {
334         int status;
335         wStream* s;
336         char* token64 = NULL;
337         int ntlmTokenLength = 0;
338         BYTE* ntlmTokenData = NULL;
339         rdpNtlm* ntlm = rdg->ntlm;
340
341         if (response->StatusCode != HTTP_STATUS_DENIED)
342         {
343                 WLog_DBG(TAG, "RDG not supported");
344                 rdg->state = RDG_CLIENT_STATE_NOT_FOUND;
345                 return FALSE;
346         }
347
348         WLog_DBG(TAG, "Out Channel authorization required");
349
350         if (ListDictionary_Contains(response->Authenticates, "NTLM"))
351         {
352                 token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
353
354                 if (!token64)
355                 {
356                         return FALSE;
357                 }
358
359                 crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
360         }
361
362         if (ntlmTokenData && ntlmTokenLength)
363         {
364                 ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
365                 ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
366         }
367
368         ntlm_authenticate(ntlm);
369
370         s = rdg_build_http_request(rdg, "RDG_OUT_DATA");
371
372         if (!s)
373                 return FALSE;
374
375         status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s));
376
377         Stream_Free(s, TRUE);
378
379         ntlm_free(rdg->ntlm);
380         rdg->ntlm = NULL;
381
382         if (status < 0)
383                 return FALSE;
384
385         rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE;
386
387         return TRUE;
388 }
389
390 BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response)
391 {
392         if (response->StatusCode != HTTP_STATUS_OK)
393         {
394                 rdg->state = RDG_CLIENT_STATE_CLOSED;
395                 return FALSE;
396         }
397
398         WLog_DBG(TAG, "Out Channel authorization complete");
399         rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED;
400
401         return TRUE;
402 }
403
404 BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response)
405 {
406         int status;
407         wStream* s;
408         char* token64 = NULL;
409         int ntlmTokenLength = 0;
410         BYTE* ntlmTokenData = NULL;
411         rdpNtlm* ntlm = rdg->ntlm;
412
413         WLog_DBG(TAG, "In Channel authorization required");
414
415         if (ListDictionary_Contains(response->Authenticates, "NTLM"))
416         {
417                 token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
418
419                 if (!token64)
420                 {
421                         return FALSE;
422                 }
423
424                 crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
425         }
426
427         if (ntlmTokenData && ntlmTokenLength)
428         {
429                 ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
430                 ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
431         }
432
433         ntlm_authenticate(ntlm);
434
435         s = rdg_build_http_request(rdg, "RDG_IN_DATA");
436
437         if (!s)
438                 return FALSE;
439
440         status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
441
442         Stream_Free(s, TRUE);
443
444         ntlm_free(rdg->ntlm);
445         rdg->ntlm = NULL;
446
447         if (status < 0)
448                 return FALSE;
449
450         rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE;
451
452         return TRUE;
453 }
454
455 BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response)
456 {
457         wStream* s;
458         int status;
459
460         if (response->StatusCode != HTTP_STATUS_OK)
461         {
462                 rdg->state = RDG_CLIENT_STATE_CLOSED;
463                 return FALSE;
464         }
465
466         WLog_DBG(TAG, "In Channel authorization complete");
467         rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED;
468
469         s = rdg_build_http_request(rdg, "RDG_IN_DATA");
470
471         if (!s)
472                 return FALSE;
473
474         status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
475         
476         Stream_Free(s, TRUE);
477
478         if (status <= 0)
479                 return FALSE;
480
481         return TRUE;
482 }
483
484 BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
485 {
486         HRESULT errorCode;
487
488         WLog_DBG(TAG, "Handshake response received");
489
490         if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
491         {
492                 return FALSE;
493         }
494
495         if (Stream_GetRemainingLength(s) < 12)
496                 return FALSE;
497
498         Stream_Seek(s, 8);
499         Stream_Read_UINT32(s, errorCode);
500
501         if (FAILED(errorCode))
502         {
503                 WLog_DBG(TAG, "Handshake error %x", errorCode);
504                 return FALSE;
505         }
506
507         return rdg_send_tunnel_request(rdg);
508 }
509
510 BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
511 {
512         HRESULT errorCode;
513
514         WLog_DBG(TAG, "Tunnel response received");
515
516         if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
517         {
518                 return FALSE;
519         }
520
521         if (Stream_GetRemainingLength(s) < 14)
522                 return FALSE;
523
524         Stream_Seek(s, 10);
525         Stream_Read_UINT32(s, errorCode);
526
527         if (FAILED(errorCode))
528         {
529                 WLog_DBG(TAG, "Tunnel creation error %x", errorCode);
530                 return FALSE;
531         }
532
533         return rdg_send_tunnel_authorization(rdg);
534 }
535
536 BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
537 {
538         HRESULT errorCode;
539
540         WLog_DBG(TAG, "Tunnel authorization received");
541
542         if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
543         {
544                 return FALSE;
545         }
546
547         if (Stream_GetRemainingLength(s) < 12)
548                 return FALSE;
549
550         Stream_Seek(s, 8);
551         Stream_Read_UINT32(s, errorCode);
552
553         if (FAILED(errorCode))
554         {
555                 WLog_DBG(TAG, "Tunnel authorization error %x", errorCode);
556                 return FALSE;
557         }
558
559         return rdg_send_channel_create(rdg);
560 }
561
562 BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
563 {
564         HRESULT errorCode;
565
566         WLog_DBG(TAG, "Channel response received");
567
568         if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
569         {
570                 return FALSE;
571         }
572
573         if (Stream_GetRemainingLength(s) < 12)
574                 return FALSE;
575
576         Stream_Seek(s, 8);
577         Stream_Read_UINT32(s, errorCode);
578
579         if (FAILED(errorCode))
580         {
581                 WLog_DBG(TAG, "Channel error %x", errorCode);
582                 return FALSE;
583         }
584
585         rdg->state = RDG_CLIENT_STATE_OPENED;
586
587         return TRUE;
588 }
589
590 BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
591 {
592         BOOL status = TRUE;
593         UINT16 type;
594
595         Stream_SetPosition(s, 0);
596
597         if (Stream_GetRemainingLength(s) < 2)
598                 return FALSE;
599
600         Stream_Peek_UINT16(s, type);
601
602         switch (type)
603         {
604                 case PKT_TYPE_HANDSHAKE_RESPONSE:
605                         status = rdg_process_handshake_response(rdg, s);
606                         break;
607
608                 case PKT_TYPE_TUNNEL_RESPONSE:
609                         status = rdg_process_tunnel_response(rdg, s);
610                         break;
611
612                 case PKT_TYPE_TUNNEL_AUTH_RESPONSE:
613                         status = rdg_process_tunnel_authorization_response(rdg, s);
614                         break;
615
616                 case PKT_TYPE_CHANNEL_RESPONSE:
617                         status = rdg_process_channel_response(rdg, s);
618                         break;
619
620                 case PKT_TYPE_DATA:
621                         assert(FALSE);
622                         return FALSE;
623         }
624
625         return status;
626 }
627
628
629 BOOL rdg_out_channel_recv(rdpRdg* rdg)
630 {
631         wStream* s;
632         BOOL status = TRUE;
633         HttpResponse* response = NULL;
634
635         switch (rdg->state)
636         {
637                 case RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST:
638                         response = http_response_recv(rdg->tlsOut);
639                         if (!response)
640                         {
641                                 return FALSE;
642                         }
643                         status = rdg_process_out_channel_response(rdg, response);
644                         http_response_free(response);
645                         break;
646
647                 case RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE:
648                         response = http_response_recv(rdg->tlsOut);
649                         if (!response)
650                         {
651                                 return FALSE;
652                         }
653                         status = rdg_process_out_channel_authorization(rdg, response);
654                         http_response_free(response);
655                         break;
656
657                 default:
658                         s = rdg_receive_packet(rdg);
659                         if (s)
660                         {
661                                 status = rdg_process_packet(rdg, s);
662                                 Stream_Free(s, TRUE);
663                         }
664         }
665
666         return status;
667 }
668
669 BOOL rdg_in_channel_recv(rdpRdg* rdg)
670 {
671         BOOL status = TRUE;
672         HttpResponse* response = NULL;
673
674         switch (rdg->state)
675         {
676                 case RDG_CLIENT_STATE_IN_CHANNEL_REQUEST:
677                         response = http_response_recv(rdg->tlsIn);
678
679                         if (!response)
680                                 return FALSE;
681
682                         status = rdg_process_in_channel_response(rdg, response);
683                         http_response_free(response);
684                         break;
685
686                 case RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE:
687                         response = http_response_recv(rdg->tlsIn);
688
689                         if (!response)
690                                 return FALSE;
691
692                         status = rdg_process_in_channel_authorization(rdg, response);
693                         http_response_free(response);
694                         break;
695         }
696
697         return status;
698 }
699
700 DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count)
701 {
702         DWORD nCount = 0;
703
704         assert(rdg != NULL);
705
706         if (events && (nCount < count))
707                 events[nCount++] = rdg->readEvent;
708         else
709                 return 0;
710
711         if (rdg->tlsOut && rdg->tlsOut->bio)
712         {
713                 if (events && (nCount < count))
714                 {
715                         BIO_get_event(rdg->tlsOut->bio, &events[nCount]);
716                         nCount++;
717                 }
718                 else
719                         return 0;
720         }
721
722         if (rdg->tlsIn && rdg->tlsIn->bio)
723         {
724                 if (events && (nCount < count))
725                 {
726                         BIO_get_event(rdg->tlsIn->bio, &events[nCount]);
727                         nCount++;
728                 }
729                 else
730                         return 0;
731         }
732
733         return nCount;
734 }
735
736 BOOL rdg_check_event_handles(rdpRdg* rdg)
737 {
738         HANDLE event = NULL;
739
740         assert(rdg != NULL);
741
742         BIO_get_event(rdg->tlsOut->bio, &event);
743
744         if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
745         {
746                 return rdg_out_channel_recv(rdg);
747         }
748
749         BIO_get_event(rdg->tlsIn->bio, &event);
750
751         if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
752         {
753                 return rdg_in_channel_recv(rdg);
754         }
755
756         return TRUE;
757 }
758
759 BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls)
760 {
761         rdpNtlm* ntlm = rdg->ntlm;
762         rdpContext* context = rdg->context;
763         rdpSettings* settings = context->settings;
764         freerdp* instance = context->instance;
765
766         if (!settings->GatewayPassword || !settings->GatewayUsername || !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername))
767         {
768                 if (instance->GatewayAuthenticate)
769                 {
770                         BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain);
771
772                         if (!proceed)
773                         {
774                                 freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
775                                 return FALSE;
776                         }
777
778                         if (settings->GatewayUseSameCredentials)
779                         {
780                                 if (settings->GatewayUsername)
781                                 {
782                                         free(settings->Username);
783                                         if (!(settings->Username = _strdup(settings->GatewayUsername)))
784                                                 return FALSE;
785                                 }
786                                 if (settings->GatewayDomain)
787                                 {
788                                         free(settings->Domain);
789                                         if (!(settings->Domain = _strdup(settings->GatewayDomain)))
790                                                 return FALSE;
791                                 }
792                                 if (settings->GatewayPassword)
793                                 {
794                                         free(settings->Password);
795                                         if (!(settings->Password = _strdup(settings->GatewayPassword)))
796                                                 return FALSE;
797                                 }
798                         }
799                 }
800         }
801
802         if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, tls->Bindings))
803         {
804                 return FALSE;
805         }
806
807         if (!ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname))
808         {
809                 return FALSE;
810         }
811
812         return TRUE;
813 }
814
815 BOOL rdg_send_out_channel_request(rdpRdg*rdg)
816 {
817         wStream* s = NULL;
818         int status;
819
820         rdg->ntlm = ntlm_new();
821
822         if (!rdg->ntlm)
823                 return FALSE;
824
825         status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsOut);
826
827         if (!status)
828                 return FALSE;
829
830         status = ntlm_authenticate(rdg->ntlm);
831
832         if (!status)
833                 return FALSE;
834
835         s = rdg_build_http_request(rdg, "RDG_OUT_DATA");
836
837         if (!s)
838                 return FALSE;
839
840         status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s));
841
842         Stream_Free(s, TRUE);
843
844         if (status < 0)
845                 return FALSE;
846
847         rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST;
848
849         return TRUE;
850 }
851
852 BOOL rdg_send_in_channel_request(rdpRdg*rdg)
853 {
854         int status;
855         wStream* s = NULL;
856
857         rdg->ntlm = ntlm_new();
858
859         if (!rdg->ntlm)
860                 return FALSE;
861
862         status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsIn);
863
864         if (!status)
865                 return FALSE;
866
867         status = ntlm_authenticate(rdg->ntlm);
868
869         if (!status)
870                 return FALSE;
871
872         s = rdg_build_http_request(rdg, "RDG_IN_DATA");
873
874         if (!s)
875                 return FALSE;
876
877         status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
878
879         Stream_Free(s, TRUE);
880
881         if (status < 0)
882                 return FALSE;
883
884         rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_REQUEST;
885
886         return TRUE;
887 }
888
889 BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
890 {
891         int sockfd = 0;
892         int status = 0;
893         BIO* socketBio = NULL;
894         BIO* bufferedBio = NULL;
895         rdpSettings* settings = rdg->settings;
896
897         assert(hostname != NULL);
898
899         sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
900
901         if (sockfd < 1)
902         {
903                 return FALSE;
904         }
905
906         socketBio = BIO_new(BIO_s_simple_socket());
907
908         if (!socketBio)
909         {
910                 closesocket(sockfd);
911                 return FALSE;
912         }
913
914         BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
915         bufferedBio = BIO_new(BIO_s_buffered_socket());
916
917         if (!bufferedBio)
918         {
919                 BIO_free(socketBio);
920                 return FALSE;
921         }
922
923         bufferedBio = BIO_push(bufferedBio, socketBio);
924         status = BIO_set_nonblock(bufferedBio, TRUE);
925
926         if (!status)
927         {
928                 BIO_free_all(bufferedBio);
929                 return FALSE;
930         }
931
932         rdg->tlsOut->hostname = settings->GatewayHostname;
933         rdg->tlsOut->port = settings->GatewayPort;
934         rdg->tlsOut->isGatewayTransport = TRUE;
935         status = tls_connect(rdg->tlsOut, bufferedBio);
936
937         if (status < 1)
938         {
939                 return FALSE;
940         }
941
942         return TRUE;
943 }
944
945 BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
946 {
947         int sockfd = 0;
948         int status = 0;
949         BIO* socketBio = NULL;
950         BIO* bufferedBio = NULL;
951         rdpSettings* settings = rdg->settings;
952
953         assert(hostname != NULL);
954
955         sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
956
957         if (sockfd < 1)
958                 return FALSE;
959
960         socketBio = BIO_new(BIO_s_simple_socket());
961
962         if (!socketBio)
963         {
964                 closesocket(sockfd);
965                 return FALSE;
966         }
967
968         BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
969         bufferedBio = BIO_new(BIO_s_buffered_socket());
970
971         if (!bufferedBio)
972         {
973                 BIO_free(socketBio);
974                 return FALSE;
975         }
976
977         bufferedBio = BIO_push(bufferedBio, socketBio);
978         status = BIO_set_nonblock(bufferedBio, TRUE);
979
980         if (!status)
981         {
982                 BIO_free_all(bufferedBio);
983                 return FALSE;
984         }
985
986         rdg->tlsIn->hostname = settings->GatewayHostname;
987         rdg->tlsIn->port = settings->GatewayPort;
988         rdg->tlsIn->isGatewayTransport = TRUE;
989         status = tls_connect(rdg->tlsIn, bufferedBio);
990
991         if (status < 1)
992         {
993                 return FALSE;
994         }
995
996         return TRUE;
997 }
998
999 BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1000 {
1001         BOOL status;
1002         DWORD nCount;
1003         HANDLE events[8];
1004
1005         assert(hostname != NULL);
1006
1007         status = rdg_tls_out_connect(rdg, hostname, port, timeout);
1008
1009         if (!status)
1010                 return FALSE;
1011
1012         status = rdg_send_out_channel_request(rdg);
1013
1014         if (!status)
1015                 return FALSE;
1016
1017         nCount = rdg_get_event_handles(rdg, events, 8);
1018
1019         if (nCount == 0)
1020                 return FALSE;
1021
1022         while (rdg->state <= RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE)
1023         {
1024                 WaitForMultipleObjects(nCount, events, FALSE, 100);
1025                 status = rdg_check_event_handles(rdg);
1026
1027                 if (!status)
1028                 {
1029                         rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1030                         return FALSE;
1031                 }
1032         }
1033
1034         return TRUE;
1035 }
1036
1037 BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1038 {
1039         BOOL status;
1040         DWORD nCount;
1041         HANDLE events[8];
1042
1043         assert(hostname != NULL);
1044
1045         status = rdg_tls_in_connect(rdg, hostname, port, timeout);
1046
1047         if (!status)
1048                 return FALSE;
1049
1050         status = rdg_send_in_channel_request(rdg);
1051
1052         if (!status)
1053                 return FALSE;
1054
1055         nCount = rdg_get_event_handles(rdg, events, 8);
1056
1057         if (nCount == 0)
1058                 return FALSE;
1059
1060         while (rdg->state <= RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE)
1061         {
1062                 WaitForMultipleObjects(nCount, events, FALSE, 100);
1063                 status = rdg_check_event_handles(rdg);
1064
1065                 if (!status)
1066                 {
1067                         rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1068                         return FALSE;
1069                 }
1070         }
1071
1072         return TRUE;
1073 }
1074
1075 BOOL rdg_tunnel_connect(rdpRdg* rdg)
1076 {
1077         BOOL status;
1078         DWORD nCount;
1079         HANDLE events[8];
1080
1081         rdg_send_handshake(rdg);
1082
1083         nCount = rdg_get_event_handles(rdg, events, 8);
1084
1085         if (nCount == 0)
1086                 return FALSE;
1087
1088         while (rdg->state < RDG_CLIENT_STATE_OPENED)
1089         {
1090                 WaitForMultipleObjects(nCount, events, FALSE, 100);
1091                 status = rdg_check_event_handles(rdg);
1092
1093                 if (!status)
1094                 {
1095                         rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1096                         return FALSE;
1097                 }
1098         }
1099
1100         return TRUE;
1101 }
1102
1103 BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1104 {
1105         BOOL status;
1106
1107         assert(rdg != NULL);
1108
1109         status = rdg_out_channel_connect(rdg, hostname, port, timeout);
1110
1111         if (!status)
1112                 return FALSE;
1113
1114         status = rdg_in_channel_connect(rdg, hostname, port, timeout);
1115
1116         if (!status)
1117                 return FALSE;
1118
1119         status = rdg_tunnel_connect(rdg);
1120
1121         if (!status)
1122                 return FALSE;
1123
1124         return TRUE;
1125 }
1126
1127 int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
1128 {
1129         int status;
1130         wStream* sChunk;
1131         int packetSize = size + 10;
1132         char chunkSize[11];
1133
1134         if (size < 1)
1135                 return 0;
1136
1137         sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1138
1139         sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1140
1141         if (!sChunk)
1142                 return -1;
1143
1144         Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1145
1146         Stream_Write_UINT16(sChunk, PKT_TYPE_DATA);   /* Type */
1147         Stream_Write_UINT16(sChunk, 0);   /* Reserved */
1148         Stream_Write_UINT32(sChunk, packetSize);   /* Packet length */
1149
1150         Stream_Write_UINT16(sChunk, size);   /* Data size */
1151         Stream_Write(sChunk, buf, size);   /* Data */
1152
1153         Stream_Write(sChunk, "\r\n", 2);
1154         Stream_SealLength(sChunk);
1155
1156         status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1157         Stream_Free(sChunk, TRUE);
1158
1159         if (status < 0)
1160                 return -1;
1161
1162         return size;
1163 }
1164
1165 BOOL rdg_process_close_packet(rdpRdg* rdg)
1166 {
1167         int status;
1168         wStream* sChunk;
1169         int packetSize = 12;
1170         char chunkSize[11];
1171     
1172         sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1173     
1174         sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1175     
1176         if (!sChunk)
1177                 return FALSE;
1178     
1179         Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1180     
1181         Stream_Write_UINT16(sChunk, PKT_TYPE_CLOSE_CHANNEL_RESPONSE);   /* Type */
1182         Stream_Write_UINT16(sChunk, 0);   /* Reserved */
1183         Stream_Write_UINT32(sChunk, packetSize);   /* Packet length */
1184     
1185         Stream_Write_UINT32(sChunk, 0);   /* Status code */
1186     
1187         Stream_Write(sChunk, "\r\n", 2);
1188         Stream_SealLength(sChunk);
1189     
1190         status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1191         Stream_Free(sChunk, TRUE);
1192     
1193         return (status < 0 ? FALSE : TRUE);
1194 }
1195
1196 BOOL rdg_process_keep_alive_packet(rdpRdg* rdg)
1197 {
1198         int status;
1199         wStream* sChunk;
1200         int packetSize = 8;
1201         char chunkSize[11];
1202     
1203         sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1204     
1205         sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1206     
1207         if (!sChunk)
1208                 return FALSE;
1209     
1210         Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1211     
1212         Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE);   /* Type */
1213         Stream_Write_UINT16(sChunk, 0);   /* Reserved */
1214         Stream_Write_UINT32(sChunk, packetSize);   /* Packet length */
1215     
1216         Stream_Write(sChunk, "\r\n", 2);
1217         Stream_SealLength(sChunk);
1218     
1219         status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1220         Stream_Free(sChunk, TRUE);
1221     
1222         return (status < 0 ? FALSE : TRUE);
1223 }
1224
1225 BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
1226 {
1227         WLog_WARN(TAG, "Unknown Control Packet received: %X", type);
1228
1229         return TRUE;
1230 }
1231
1232 BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength)
1233 {
1234         wStream* s = NULL;
1235         int readCount = 0;
1236         int status;
1237         int payloadSize = packetLength - sizeof(RdgPacketHeader);
1238
1239         if (payloadSize)
1240         {
1241                 s = Stream_New(NULL, payloadSize);
1242
1243                 if (!s)
1244                         return FALSE;
1245
1246                 while (readCount < payloadSize)
1247                 {
1248                         status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);
1249
1250                         if (status <= 0)
1251                         {
1252                                 if (!BIO_should_retry(rdg->tlsOut->bio))
1253                                 {
1254                                         Stream_Free(s, TRUE);
1255                                         return FALSE;
1256                                 }
1257                                 continue;
1258                         }
1259
1260                         Stream_Seek(s, status);
1261                         readCount += status;
1262                 }
1263         }
1264
1265         switch (type)
1266         {
1267                 case PKT_TYPE_CLOSE_CHANNEL:
1268                         EnterCriticalSection(&rdg->writeSection);
1269                         status = rdg_process_close_packet(rdg);
1270                         LeaveCriticalSection(&rdg->writeSection);
1271                         break;
1272
1273                 case PKT_TYPE_KEEPALIVE:
1274                         EnterCriticalSection(&rdg->writeSection);
1275                         status = rdg_process_keep_alive_packet(rdg);
1276                         LeaveCriticalSection(&rdg->writeSection);
1277                         break;
1278             
1279                 default:
1280                         status = rdg_process_unknown_packet(rdg, type);
1281                         break;
1282         }
1283
1284         Stream_Free(s, TRUE);
1285
1286         return status;
1287 }
1288
1289 int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
1290 {
1291         RdgPacketHeader header;
1292         int readCount = 0;
1293         int readSize;
1294         int status;
1295         int pending;
1296
1297         if (!rdg->packetRemainingCount)
1298         {
1299                 while (readCount < sizeof(RdgPacketHeader))
1300                 {
1301                         status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, sizeof(RdgPacketHeader) - readCount);
1302
1303                         if (status <= 0)
1304                         {
1305                                 if (!BIO_should_retry(rdg->tlsOut->bio))
1306                                 {
1307                                         return -1;
1308                                 }
1309                                 if (!readCount)
1310                                 {
1311                                         return 0;
1312                                 }
1313                                 continue;
1314                         }
1315
1316                         readCount += status;
1317                 }
1318
1319                 if (header.type != PKT_TYPE_DATA)
1320                 {
1321                         status = rdg_process_control_packet(rdg, header.type, header.packetLength);
1322                         if (!status)
1323                         {
1324                                 return -1;
1325                         }
1326                         return 0;
1327                 }
1328
1329                 readCount = 0;
1330
1331                 while (readCount < 2)
1332                 {
1333                         status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, 2 - readCount);
1334
1335                         if (status < 0)
1336                         {
1337                                 if (!BIO_should_retry(rdg->tlsOut->bio))
1338                                 {
1339                                         return -1;
1340                                 }
1341                                 continue;
1342                         }
1343
1344                         readCount += status;
1345                 }
1346         }
1347
1348         readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size);
1349
1350         status = BIO_read(rdg->tlsOut->bio, buffer, readSize);
1351
1352         if (status <= 0)
1353         {
1354                 if (!BIO_should_retry(rdg->tlsOut->bio))
1355                 {
1356                         return -1;
1357                 }
1358                 return 0;
1359         }
1360
1361         rdg->packetRemainingCount -= status;
1362
1363         pending = BIO_pending(rdg->tlsOut->bio);
1364
1365         if (pending > 0)
1366                 SetEvent(rdg->readEvent);
1367         else
1368                 ResetEvent(rdg->readEvent);
1369
1370         return status;
1371 }
1372
1373 long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
1374 {
1375         return 1;
1376 }
1377
1378 static int rdg_bio_write(BIO* bio, const char* buf, int num)
1379 {
1380         int status;
1381         rdpRdg* rdg = (rdpRdg*)bio->ptr;
1382
1383         BIO_clear_flags(bio, BIO_FLAGS_WRITE);
1384
1385         EnterCriticalSection(&rdg->writeSection);
1386         status = rdg_write_data_packet(rdg, (BYTE*) buf, num);
1387         LeaveCriticalSection(&rdg->writeSection);
1388
1389         if (status < 0)
1390         {
1391                 BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
1392                 return -1;
1393         }
1394         else if (status < num)
1395         {
1396                 BIO_set_flags(bio, BIO_FLAGS_WRITE);
1397                 WSASetLastError(WSAEWOULDBLOCK);
1398         }
1399         else
1400         {
1401                 BIO_clear_flags(bio, BIO_FLAGS_WRITE);
1402         }
1403
1404         return status;
1405 }
1406
1407 static int rdg_bio_read(BIO* bio, char* buf, int size)
1408 {
1409         int status;
1410         rdpRdg* rdg = (rdpRdg*) bio->ptr;
1411
1412         status = rdg_read_data_packet(rdg, (BYTE*) buf, size);
1413
1414         if (!status)
1415         {
1416                 BIO_set_retry_read(bio);
1417                 return -1;
1418         }
1419         else if (status < 0)
1420         {
1421                 BIO_clear_retry_flags(bio);
1422                 return -1;
1423         }
1424
1425         return status;
1426 }
1427
1428 static int rdg_bio_puts(BIO* bio, const char* str)
1429 {
1430         return -2;
1431 }
1432
1433 static int rdg_bio_gets(BIO* bio, char* str, int size)
1434 {
1435         return -2;
1436 }
1437
1438 static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
1439 {
1440         int status = 0;
1441         rdpRdg* rdg = (rdpRdg*)bio->ptr;
1442         rdpTls* tlsOut = rdg->tlsOut;
1443         rdpTls* tlsIn = rdg->tlsIn;
1444
1445         if (cmd == BIO_CTRL_FLUSH)
1446         {
1447                 (void)BIO_flush(tlsOut->bio);
1448                 (void)BIO_flush(tlsIn->bio);
1449                 status = 1;
1450         }
1451         else if (cmd == BIO_C_GET_EVENT)
1452         {
1453                 if (arg2)
1454                 {
1455                         BIO_get_event(rdg->tlsOut->bio, arg2);
1456                         status = 1;
1457                 }
1458         }
1459         else if (cmd == BIO_C_SET_NONBLOCK)
1460         {
1461                 status = 1;
1462         }
1463         else if (cmd == BIO_C_READ_BLOCKED)
1464         {
1465                 status = 0;
1466         }
1467         else if (cmd == BIO_C_WRITE_BLOCKED)
1468         {
1469                 status = 0;
1470         }
1471         else if (cmd == BIO_C_WAIT_READ)
1472         {
1473                 int timeout = (int)arg1;
1474                 return BIO_wait_read(tlsOut->bio, timeout);
1475         }
1476         else if (cmd == BIO_C_WAIT_WRITE)
1477         {
1478                 status = 0;
1479         }
1480
1481         return status;
1482 }
1483
1484 static int rdg_bio_new(BIO* bio)
1485 {
1486         bio->init = 1;
1487         bio->num = 0;
1488         bio->ptr = NULL;
1489         bio->flags = BIO_FLAGS_SHOULD_RETRY;
1490         return 1;
1491 }
1492
1493 static int rdg_bio_free(BIO* bio)
1494 {
1495         return 1;
1496 }
1497
1498 static BIO_METHOD rdg_bio_methods =
1499 {
1500         BIO_TYPE_TSG,
1501         "RDGateway",
1502         rdg_bio_write,
1503         rdg_bio_read,
1504         rdg_bio_puts,
1505         rdg_bio_gets,
1506         rdg_bio_ctrl,
1507         rdg_bio_new,
1508         rdg_bio_free,
1509         NULL,
1510 };
1511
1512 BIO_METHOD* BIO_s_rdg(void)
1513 {
1514         return &rdg_bio_methods;
1515 }
1516
1517 rdpRdg* rdg_new(rdpTransport* transport)
1518 {
1519         rdpRdg* rdg;
1520         RPC_CSTR stringUuid;
1521         char bracedUuid[40];
1522         RPC_STATUS rpcStatus;
1523
1524         assert(transport != NULL);
1525
1526         rdg = (rdpRdg*) calloc(1, sizeof(rdpRdg));
1527
1528         if (rdg)
1529         {
1530                 rdg->state = RDG_CLIENT_STATE_INITIAL;
1531                 rdg->context = transport->context;
1532                 rdg->settings = rdg->context->settings;
1533
1534                 UuidCreate(&rdg->guid);
1535
1536                 rpcStatus = UuidToStringA(&rdg->guid, &stringUuid);
1537
1538                 if (rpcStatus == RPC_S_OUT_OF_MEMORY)
1539                         goto rdg_alloc_error;
1540
1541                 sprintf_s(bracedUuid, sizeof(bracedUuid), "{%s}", stringUuid);
1542                 RpcStringFreeA(&stringUuid);
1543
1544                 rdg->tlsOut = tls_new(rdg->settings);
1545
1546                 if (!rdg->tlsOut)
1547                         goto rdg_alloc_error;
1548
1549                 rdg->tlsIn = tls_new(rdg->settings);
1550
1551                 if (!rdg->tlsIn)
1552                         goto rdg_alloc_error;
1553
1554                 rdg->http = http_context_new();
1555
1556                 if (!rdg->http)
1557                         goto rdg_alloc_error;
1558
1559                 http_context_set_uri(rdg->http, "/remoteDesktopGateway/");
1560                 http_context_set_accept(rdg->http, "*/*");
1561                 http_context_set_cache_control(rdg->http, "no-cache");
1562                 http_context_set_pragma(rdg->http, "no-cache");
1563                 http_context_set_connection(rdg->http, "Keep-Alive");
1564                 http_context_set_user_agent(rdg->http, "MS-RDGateway/1.0");
1565                 http_context_set_host(rdg->http, rdg->settings->GatewayHostname);
1566                 http_context_set_rdg_connection_id(rdg->http, bracedUuid);
1567
1568                 if (!rdg->http->URI || !rdg->http->Accept || !rdg->http->CacheControl ||
1569                                 !rdg->http->Pragma || !rdg->http->Connection || !rdg->http->UserAgent
1570                                 || !rdg->http->Host || !rdg->http->RdgConnectionId)
1571                 {
1572                         goto rdg_alloc_error;
1573                 }
1574
1575                 rdg->frontBio = BIO_new(BIO_s_rdg());
1576
1577                 if (!rdg->frontBio)
1578                         goto rdg_alloc_error;
1579
1580                 rdg->frontBio->ptr = rdg;
1581
1582                 rdg->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1583
1584                 if (!rdg->readEvent)
1585                         goto rdg_alloc_error;
1586         
1587                 InitializeCriticalSection(&rdg->writeSection);
1588         }
1589
1590         return rdg;
1591
1592 rdg_alloc_error:
1593         rdg_free(rdg);
1594         return NULL;
1595 }
1596
1597 void rdg_free(rdpRdg* rdg)
1598 {
1599         if (!rdg)
1600                 return;
1601
1602         if (rdg->tlsOut)
1603         {
1604                 tls_free(rdg->tlsOut);
1605                 rdg->tlsOut = NULL;
1606         }
1607
1608         if (rdg->tlsIn)
1609         {
1610                 tls_free(rdg->tlsIn);
1611                 rdg->tlsIn = NULL;
1612         }
1613
1614         if (rdg->http)
1615         {
1616                 http_context_free(rdg->http);
1617                 rdg->http = NULL;
1618         }
1619
1620         if (rdg->ntlm)
1621         {
1622                 ntlm_free(rdg->ntlm);
1623                 rdg->ntlm = NULL;
1624         }
1625
1626         if (rdg->readEvent)
1627         {
1628                 CloseHandle(rdg->readEvent);
1629                 rdg->readEvent = NULL;
1630         }
1631     
1632         DeleteCriticalSection(&rdg->writeSection);
1633
1634         free(rdg);
1635 }