2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Remote Desktop Gateway (RDG)
5 * Copyright 2015 Denis Vincent <dvincent@devolutions.net>
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
32 #include <freerdp/log.h>
33 #include <freerdp/error.h>
34 #include <freerdp/utils/ringbuffer.h>
39 #define TAG FREERDP_TAG("core.gateway.rdg")
43 typedef struct rdg_packet_header
52 BOOL rdg_write_packet(rdpRdg* rdg, wStream* sPacket)
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);
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);
69 status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
70 Stream_Free(sChunk, TRUE);
78 wStream* rdg_receive_packet(rdpRdg* rdg)
82 RdgPacketHeader* packet;
85 s = Stream_New(NULL, 1024);
90 packet = (RdgPacketHeader*) Stream_Buffer(s);
92 while (readCount < sizeof(RdgPacketHeader))
94 status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);
102 Stream_Seek(s, readCount);
105 if (Stream_Capacity(s) < packet->packetLength)
107 if (!Stream_EnsureCapacity(s, packet->packetLength))
109 Stream_Free(s, TRUE);
112 packet = (RdgPacketHeader*) Stream_Buffer(s);
115 while (readCount < packet->packetLength)
117 status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), packet->packetLength - readCount);
125 Stream_Seek(s, readCount);
128 Stream_SealLength(s);
133 BOOL rdg_send_handshake(rdpRdg* rdg)
138 s = Stream_New(NULL, 14);
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) */
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) */
152 Stream_SealLength(s);
154 status = rdg_write_packet(rdg, s);
155 Stream_Free(s, TRUE);
159 rdg->state = RDG_CLIENT_STATE_HANDSHAKE;
165 BOOL rdg_send_tunnel_request(rdpRdg* rdg)
170 s = Stream_New(NULL, 16);
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) */
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 */
183 Stream_SealLength(s);
185 status = rdg_write_packet(rdg, s);
186 Stream_Free(s, TRUE);
190 rdg->state = RDG_CLIENT_STATE_TUNNEL_CREATE;
196 BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
201 char* clientName = rdg->settings->ClientHostname;
202 UINT16 clientNameLen = strlen(clientName) + 1;
203 UINT32 packetSize = 12 + clientNameLen * 2;
205 s = Stream_New(NULL, packetSize);
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) */
214 Stream_Write_UINT16(s, 0); /* FieldsPresent (2 bytes) */
215 Stream_Write_UINT16(s, clientNameLen * 2); /* Client name string length */
217 for (i = 0; i < clientNameLen; i++)
219 Stream_Write_UINT16(s, clientName[i]);
222 Stream_SealLength(s);
224 status = rdg_write_packet(rdg, s);
226 Stream_Free(s, TRUE);
230 rdg->state = RDG_CLIENT_STATE_TUNNEL_AUTHORIZE;
236 BOOL rdg_send_channel_create(rdpRdg* rdg)
241 char* serverName = rdg->settings->ServerHostname;
242 UINT16 serverNameLen = strlen(serverName) + 1;
243 UINT32 packetSize = 16 + serverNameLen * 2;
245 s = Stream_New(NULL, packetSize);
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) */
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);
260 for (i = 0; i < serverNameLen; i++)
262 Stream_Write_UINT16(s, serverName[i]);
265 Stream_SealLength(s);
267 status = rdg_write_packet(rdg, s);
269 Stream_Free(s, TRUE);
273 rdg->state = RDG_CLIENT_STATE_CHANNEL_CREATE;
279 wStream* rdg_build_http_request(rdpRdg* rdg, char* method)
282 HttpRequest* request = NULL;
283 SecBuffer* ntlmToken = NULL;
284 char* base64NtlmToken = NULL;
286 assert(method != NULL);
288 request = http_request_new();
293 http_request_set_method(request, method);
294 http_request_set_uri(request, rdg->http->URI);
296 if (!request->Method || !request->URI)
301 ntlmToken = rdg->ntlm->outputBuffer;
304 base64NtlmToken = crypto_base64_encode(ntlmToken->pvBuffer, ntlmToken->cbBuffer);
308 http_request_set_auth_scheme(request, "NTLM");
309 http_request_set_auth_param(request, base64NtlmToken);
311 free(base64NtlmToken);
313 if (!request->AuthScheme || !request->AuthParam)
318 if (rdg->state == RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED)
320 http_request_set_transfer_encoding(request, "chunked");
323 s = http_request_write(rdg->http, request);
324 http_request_free(request);
327 Stream_SealLength(s);
332 BOOL rdg_process_out_channel_response(rdpRdg* rdg, HttpResponse* response)
336 char* token64 = NULL;
337 int ntlmTokenLength = 0;
338 BYTE* ntlmTokenData = NULL;
339 rdpNtlm* ntlm = rdg->ntlm;
341 if (response->StatusCode != HTTP_STATUS_DENIED)
343 WLog_DBG(TAG, "RDG not supported");
344 rdg->state = RDG_CLIENT_STATE_NOT_FOUND;
348 WLog_DBG(TAG, "Out Channel authorization required");
350 if (ListDictionary_Contains(response->Authenticates, "NTLM"))
352 token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
359 crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
362 if (ntlmTokenData && ntlmTokenLength)
364 ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
365 ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
368 ntlm_authenticate(ntlm);
370 s = rdg_build_http_request(rdg, "RDG_OUT_DATA");
375 status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s));
377 Stream_Free(s, TRUE);
379 ntlm_free(rdg->ntlm);
385 rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE;
390 BOOL rdg_process_out_channel_authorization(rdpRdg* rdg, HttpResponse* response)
392 if (response->StatusCode != HTTP_STATUS_OK)
394 rdg->state = RDG_CLIENT_STATE_CLOSED;
398 WLog_DBG(TAG, "Out Channel authorization complete");
399 rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZED;
404 BOOL rdg_process_in_channel_response(rdpRdg* rdg, HttpResponse* response)
408 char* token64 = NULL;
409 int ntlmTokenLength = 0;
410 BYTE* ntlmTokenData = NULL;
411 rdpNtlm* ntlm = rdg->ntlm;
413 WLog_DBG(TAG, "In Channel authorization required");
415 if (ListDictionary_Contains(response->Authenticates, "NTLM"))
417 token64 = ListDictionary_GetItemValue(response->Authenticates, "NTLM");
424 crypto_base64_decode(token64, strlen(token64), &ntlmTokenData, &ntlmTokenLength);
427 if (ntlmTokenData && ntlmTokenLength)
429 ntlm->inputBuffer[0].pvBuffer = ntlmTokenData;
430 ntlm->inputBuffer[0].cbBuffer = ntlmTokenLength;
433 ntlm_authenticate(ntlm);
435 s = rdg_build_http_request(rdg, "RDG_IN_DATA");
440 status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
442 Stream_Free(s, TRUE);
444 ntlm_free(rdg->ntlm);
450 rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE;
455 BOOL rdg_process_in_channel_authorization(rdpRdg* rdg, HttpResponse* response)
460 if (response->StatusCode != HTTP_STATUS_OK)
462 rdg->state = RDG_CLIENT_STATE_CLOSED;
466 WLog_DBG(TAG, "In Channel authorization complete");
467 rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZED;
469 s = rdg_build_http_request(rdg, "RDG_IN_DATA");
474 status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
476 Stream_Free(s, TRUE);
484 BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
488 WLog_DBG(TAG, "Handshake response received");
490 if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
495 if (Stream_GetRemainingLength(s) < 12)
499 Stream_Read_UINT32(s, errorCode);
501 if (FAILED(errorCode))
503 WLog_DBG(TAG, "Handshake error %x", errorCode);
507 return rdg_send_tunnel_request(rdg);
510 BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
514 WLog_DBG(TAG, "Tunnel response received");
516 if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
521 if (Stream_GetRemainingLength(s) < 14)
525 Stream_Read_UINT32(s, errorCode);
527 if (FAILED(errorCode))
529 WLog_DBG(TAG, "Tunnel creation error %x", errorCode);
533 return rdg_send_tunnel_authorization(rdg);
536 BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
540 WLog_DBG(TAG, "Tunnel authorization received");
542 if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
547 if (Stream_GetRemainingLength(s) < 12)
551 Stream_Read_UINT32(s, errorCode);
553 if (FAILED(errorCode))
555 WLog_DBG(TAG, "Tunnel authorization error %x", errorCode);
559 return rdg_send_channel_create(rdg);
562 BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
566 WLog_DBG(TAG, "Channel response received");
568 if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
573 if (Stream_GetRemainingLength(s) < 12)
577 Stream_Read_UINT32(s, errorCode);
579 if (FAILED(errorCode))
581 WLog_DBG(TAG, "Channel error %x", errorCode);
585 rdg->state = RDG_CLIENT_STATE_OPENED;
590 BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
595 Stream_SetPosition(s, 0);
597 if (Stream_GetRemainingLength(s) < 2)
600 Stream_Peek_UINT16(s, type);
604 case PKT_TYPE_HANDSHAKE_RESPONSE:
605 status = rdg_process_handshake_response(rdg, s);
608 case PKT_TYPE_TUNNEL_RESPONSE:
609 status = rdg_process_tunnel_response(rdg, s);
612 case PKT_TYPE_TUNNEL_AUTH_RESPONSE:
613 status = rdg_process_tunnel_authorization_response(rdg, s);
616 case PKT_TYPE_CHANNEL_RESPONSE:
617 status = rdg_process_channel_response(rdg, s);
629 BOOL rdg_out_channel_recv(rdpRdg* rdg)
633 HttpResponse* response = NULL;
637 case RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST:
638 response = http_response_recv(rdg->tlsOut);
643 status = rdg_process_out_channel_response(rdg, response);
644 http_response_free(response);
647 case RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE:
648 response = http_response_recv(rdg->tlsOut);
653 status = rdg_process_out_channel_authorization(rdg, response);
654 http_response_free(response);
658 s = rdg_receive_packet(rdg);
661 status = rdg_process_packet(rdg, s);
662 Stream_Free(s, TRUE);
669 BOOL rdg_in_channel_recv(rdpRdg* rdg)
672 HttpResponse* response = NULL;
676 case RDG_CLIENT_STATE_IN_CHANNEL_REQUEST:
677 response = http_response_recv(rdg->tlsIn);
682 status = rdg_process_in_channel_response(rdg, response);
683 http_response_free(response);
686 case RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE:
687 response = http_response_recv(rdg->tlsIn);
692 status = rdg_process_in_channel_authorization(rdg, response);
693 http_response_free(response);
700 DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count)
706 if (events && (nCount < count))
707 events[nCount++] = rdg->readEvent;
711 if (rdg->tlsOut && rdg->tlsOut->bio)
713 if (events && (nCount < count))
715 BIO_get_event(rdg->tlsOut->bio, &events[nCount]);
722 if (rdg->tlsIn && rdg->tlsIn->bio)
724 if (events && (nCount < count))
726 BIO_get_event(rdg->tlsIn->bio, &events[nCount]);
736 BOOL rdg_check_event_handles(rdpRdg* rdg)
742 BIO_get_event(rdg->tlsOut->bio, &event);
744 if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
746 return rdg_out_channel_recv(rdg);
749 BIO_get_event(rdg->tlsIn->bio, &event);
751 if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0)
753 return rdg_in_channel_recv(rdg);
759 BOOL rdg_ncacn_http_ntlm_init(rdpRdg* rdg, rdpTls* tls)
761 rdpNtlm* ntlm = rdg->ntlm;
762 rdpContext* context = rdg->context;
763 rdpSettings* settings = context->settings;
764 freerdp* instance = context->instance;
766 if (!settings->GatewayPassword || !settings->GatewayUsername || !strlen(settings->GatewayPassword) || !strlen(settings->GatewayUsername))
768 if (instance->GatewayAuthenticate)
770 BOOL proceed = instance->GatewayAuthenticate(instance, &settings->GatewayUsername, &settings->GatewayPassword, &settings->GatewayDomain);
774 freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
778 if (settings->GatewayUseSameCredentials)
780 if (settings->GatewayUsername)
782 free(settings->Username);
783 if (!(settings->Username = _strdup(settings->GatewayUsername)))
786 if (settings->GatewayDomain)
788 free(settings->Domain);
789 if (!(settings->Domain = _strdup(settings->GatewayDomain)))
792 if (settings->GatewayPassword)
794 free(settings->Password);
795 if (!(settings->Password = _strdup(settings->GatewayPassword)))
802 if (!ntlm_client_init(ntlm, TRUE, settings->GatewayUsername, settings->GatewayDomain, settings->GatewayPassword, tls->Bindings))
807 if (!ntlm_client_make_spn(ntlm, _T("HTTP"), settings->GatewayHostname))
815 BOOL rdg_send_out_channel_request(rdpRdg*rdg)
820 rdg->ntlm = ntlm_new();
825 status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsOut);
830 status = ntlm_authenticate(rdg->ntlm);
835 s = rdg_build_http_request(rdg, "RDG_OUT_DATA");
840 status = tls_write_all(rdg->tlsOut, Stream_Buffer(s), Stream_Length(s));
842 Stream_Free(s, TRUE);
847 rdg->state = RDG_CLIENT_STATE_OUT_CHANNEL_REQUEST;
852 BOOL rdg_send_in_channel_request(rdpRdg*rdg)
857 rdg->ntlm = ntlm_new();
862 status = rdg_ncacn_http_ntlm_init(rdg, rdg->tlsIn);
867 status = ntlm_authenticate(rdg->ntlm);
872 s = rdg_build_http_request(rdg, "RDG_IN_DATA");
877 status = tls_write_all(rdg->tlsIn, Stream_Buffer(s), Stream_Length(s));
879 Stream_Free(s, TRUE);
884 rdg->state = RDG_CLIENT_STATE_IN_CHANNEL_REQUEST;
889 BOOL rdg_tls_out_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
893 BIO* socketBio = NULL;
894 BIO* bufferedBio = NULL;
895 rdpSettings* settings = rdg->settings;
897 assert(hostname != NULL);
899 sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
906 socketBio = BIO_new(BIO_s_simple_socket());
914 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
915 bufferedBio = BIO_new(BIO_s_buffered_socket());
923 bufferedBio = BIO_push(bufferedBio, socketBio);
924 status = BIO_set_nonblock(bufferedBio, TRUE);
928 BIO_free_all(bufferedBio);
932 rdg->tlsOut->hostname = settings->GatewayHostname;
933 rdg->tlsOut->port = settings->GatewayPort;
934 rdg->tlsOut->isGatewayTransport = TRUE;
935 status = tls_connect(rdg->tlsOut, bufferedBio);
945 BOOL rdg_tls_in_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
949 BIO* socketBio = NULL;
950 BIO* bufferedBio = NULL;
951 rdpSettings* settings = rdg->settings;
953 assert(hostname != NULL);
955 sockfd = freerdp_tcp_connect(settings, settings->GatewayHostname, settings->GatewayPort, timeout);
960 socketBio = BIO_new(BIO_s_simple_socket());
968 BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
969 bufferedBio = BIO_new(BIO_s_buffered_socket());
977 bufferedBio = BIO_push(bufferedBio, socketBio);
978 status = BIO_set_nonblock(bufferedBio, TRUE);
982 BIO_free_all(bufferedBio);
986 rdg->tlsIn->hostname = settings->GatewayHostname;
987 rdg->tlsIn->port = settings->GatewayPort;
988 rdg->tlsIn->isGatewayTransport = TRUE;
989 status = tls_connect(rdg->tlsIn, bufferedBio);
999 BOOL rdg_out_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1005 assert(hostname != NULL);
1007 status = rdg_tls_out_connect(rdg, hostname, port, timeout);
1012 status = rdg_send_out_channel_request(rdg);
1017 nCount = rdg_get_event_handles(rdg, events, 8);
1022 while (rdg->state <= RDG_CLIENT_STATE_OUT_CHANNEL_AUTHORIZE)
1024 WaitForMultipleObjects(nCount, events, FALSE, 100);
1025 status = rdg_check_event_handles(rdg);
1029 rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1037 BOOL rdg_in_channel_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1043 assert(hostname != NULL);
1045 status = rdg_tls_in_connect(rdg, hostname, port, timeout);
1050 status = rdg_send_in_channel_request(rdg);
1055 nCount = rdg_get_event_handles(rdg, events, 8);
1060 while (rdg->state <= RDG_CLIENT_STATE_IN_CHANNEL_AUTHORIZE)
1062 WaitForMultipleObjects(nCount, events, FALSE, 100);
1063 status = rdg_check_event_handles(rdg);
1067 rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1075 BOOL rdg_tunnel_connect(rdpRdg* rdg)
1081 rdg_send_handshake(rdg);
1083 nCount = rdg_get_event_handles(rdg, events, 8);
1088 while (rdg->state < RDG_CLIENT_STATE_OPENED)
1090 WaitForMultipleObjects(nCount, events, FALSE, 100);
1091 status = rdg_check_event_handles(rdg);
1095 rdg->context->rdp->transport->layer = TRANSPORT_LAYER_CLOSED;
1103 BOOL rdg_connect(rdpRdg* rdg, const char* hostname, UINT16 port, int timeout)
1107 assert(rdg != NULL);
1109 status = rdg_out_channel_connect(rdg, hostname, port, timeout);
1114 status = rdg_in_channel_connect(rdg, hostname, port, timeout);
1119 status = rdg_tunnel_connect(rdg);
1127 int rdg_write_data_packet(rdpRdg* rdg, BYTE* buf, int size)
1131 int packetSize = size + 10;
1137 sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1139 sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1144 Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1146 Stream_Write_UINT16(sChunk, PKT_TYPE_DATA); /* Type */
1147 Stream_Write_UINT16(sChunk, 0); /* Reserved */
1148 Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
1150 Stream_Write_UINT16(sChunk, size); /* Data size */
1151 Stream_Write(sChunk, buf, size); /* Data */
1153 Stream_Write(sChunk, "\r\n", 2);
1154 Stream_SealLength(sChunk);
1156 status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1157 Stream_Free(sChunk, TRUE);
1165 BOOL rdg_process_close_packet(rdpRdg* rdg)
1169 int packetSize = 12;
1172 sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1174 sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1179 Stream_Write(sChunk, chunkSize, strlen(chunkSize));
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 */
1185 Stream_Write_UINT32(sChunk, 0); /* Status code */
1187 Stream_Write(sChunk, "\r\n", 2);
1188 Stream_SealLength(sChunk);
1190 status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1191 Stream_Free(sChunk, TRUE);
1193 return (status < 0 ? FALSE : TRUE);
1196 BOOL rdg_process_keep_alive_packet(rdpRdg* rdg)
1203 sprintf_s(chunkSize, sizeof(chunkSize), "%X\r\n", packetSize);
1205 sChunk = Stream_New(NULL, strlen(chunkSize) + packetSize + 2);
1210 Stream_Write(sChunk, chunkSize, strlen(chunkSize));
1212 Stream_Write_UINT16(sChunk, PKT_TYPE_KEEPALIVE); /* Type */
1213 Stream_Write_UINT16(sChunk, 0); /* Reserved */
1214 Stream_Write_UINT32(sChunk, packetSize); /* Packet length */
1216 Stream_Write(sChunk, "\r\n", 2);
1217 Stream_SealLength(sChunk);
1219 status = tls_write_all(rdg->tlsIn, Stream_Buffer(sChunk), Stream_Length(sChunk));
1220 Stream_Free(sChunk, TRUE);
1222 return (status < 0 ? FALSE : TRUE);
1225 BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
1227 WLog_WARN(TAG, "Unknown Control Packet received: %X", type);
1232 BOOL rdg_process_control_packet(rdpRdg* rdg, int type, int packetLength)
1237 int payloadSize = packetLength - sizeof(RdgPacketHeader);
1241 s = Stream_New(NULL, payloadSize);
1246 while (readCount < payloadSize)
1248 status = BIO_read(rdg->tlsOut->bio, Stream_Pointer(s), sizeof(RdgPacketHeader) - readCount);
1252 if (!BIO_should_retry(rdg->tlsOut->bio))
1254 Stream_Free(s, TRUE);
1260 Stream_Seek(s, status);
1261 readCount += status;
1267 case PKT_TYPE_CLOSE_CHANNEL:
1268 EnterCriticalSection(&rdg->writeSection);
1269 status = rdg_process_close_packet(rdg);
1270 LeaveCriticalSection(&rdg->writeSection);
1273 case PKT_TYPE_KEEPALIVE:
1274 EnterCriticalSection(&rdg->writeSection);
1275 status = rdg_process_keep_alive_packet(rdg);
1276 LeaveCriticalSection(&rdg->writeSection);
1280 status = rdg_process_unknown_packet(rdg, type);
1284 Stream_Free(s, TRUE);
1289 int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
1291 RdgPacketHeader header;
1297 if (!rdg->packetRemainingCount)
1299 while (readCount < sizeof(RdgPacketHeader))
1301 status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount, sizeof(RdgPacketHeader) - readCount);
1305 if (!BIO_should_retry(rdg->tlsOut->bio))
1316 readCount += status;
1319 if (header.type != PKT_TYPE_DATA)
1321 status = rdg_process_control_packet(rdg, header.type, header.packetLength);
1331 while (readCount < 2)
1333 status = BIO_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount, 2 - readCount);
1337 if (!BIO_should_retry(rdg->tlsOut->bio))
1344 readCount += status;
1348 readSize = (rdg->packetRemainingCount < size ? rdg->packetRemainingCount : size);
1350 status = BIO_read(rdg->tlsOut->bio, buffer, readSize);
1354 if (!BIO_should_retry(rdg->tlsOut->bio))
1361 rdg->packetRemainingCount -= status;
1363 pending = BIO_pending(rdg->tlsOut->bio);
1366 SetEvent(rdg->readEvent);
1368 ResetEvent(rdg->readEvent);
1373 long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl, long ret)
1378 static int rdg_bio_write(BIO* bio, const char* buf, int num)
1381 rdpRdg* rdg = (rdpRdg*)bio->ptr;
1383 BIO_clear_flags(bio, BIO_FLAGS_WRITE);
1385 EnterCriticalSection(&rdg->writeSection);
1386 status = rdg_write_data_packet(rdg, (BYTE*) buf, num);
1387 LeaveCriticalSection(&rdg->writeSection);
1391 BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
1394 else if (status < num)
1396 BIO_set_flags(bio, BIO_FLAGS_WRITE);
1397 WSASetLastError(WSAEWOULDBLOCK);
1401 BIO_clear_flags(bio, BIO_FLAGS_WRITE);
1407 static int rdg_bio_read(BIO* bio, char* buf, int size)
1410 rdpRdg* rdg = (rdpRdg*) bio->ptr;
1412 status = rdg_read_data_packet(rdg, (BYTE*) buf, size);
1416 BIO_set_retry_read(bio);
1419 else if (status < 0)
1421 BIO_clear_retry_flags(bio);
1428 static int rdg_bio_puts(BIO* bio, const char* str)
1433 static int rdg_bio_gets(BIO* bio, char* str, int size)
1438 static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
1441 rdpRdg* rdg = (rdpRdg*)bio->ptr;
1442 rdpTls* tlsOut = rdg->tlsOut;
1443 rdpTls* tlsIn = rdg->tlsIn;
1445 if (cmd == BIO_CTRL_FLUSH)
1447 (void)BIO_flush(tlsOut->bio);
1448 (void)BIO_flush(tlsIn->bio);
1451 else if (cmd == BIO_C_GET_EVENT)
1455 BIO_get_event(rdg->tlsOut->bio, arg2);
1459 else if (cmd == BIO_C_SET_NONBLOCK)
1463 else if (cmd == BIO_C_READ_BLOCKED)
1467 else if (cmd == BIO_C_WRITE_BLOCKED)
1471 else if (cmd == BIO_C_WAIT_READ)
1473 int timeout = (int)arg1;
1474 return BIO_wait_read(tlsOut->bio, timeout);
1476 else if (cmd == BIO_C_WAIT_WRITE)
1484 static int rdg_bio_new(BIO* bio)
1489 bio->flags = BIO_FLAGS_SHOULD_RETRY;
1493 static int rdg_bio_free(BIO* bio)
1498 static BIO_METHOD rdg_bio_methods =
1512 BIO_METHOD* BIO_s_rdg(void)
1514 return &rdg_bio_methods;
1517 rdpRdg* rdg_new(rdpTransport* transport)
1520 RPC_CSTR stringUuid;
1521 char bracedUuid[40];
1522 RPC_STATUS rpcStatus;
1524 assert(transport != NULL);
1526 rdg = (rdpRdg*) calloc(1, sizeof(rdpRdg));
1530 rdg->state = RDG_CLIENT_STATE_INITIAL;
1531 rdg->context = transport->context;
1532 rdg->settings = rdg->context->settings;
1534 UuidCreate(&rdg->guid);
1536 rpcStatus = UuidToStringA(&rdg->guid, &stringUuid);
1538 if (rpcStatus == RPC_S_OUT_OF_MEMORY)
1539 goto rdg_alloc_error;
1541 sprintf_s(bracedUuid, sizeof(bracedUuid), "{%s}", stringUuid);
1542 RpcStringFreeA(&stringUuid);
1544 rdg->tlsOut = tls_new(rdg->settings);
1547 goto rdg_alloc_error;
1549 rdg->tlsIn = tls_new(rdg->settings);
1552 goto rdg_alloc_error;
1554 rdg->http = http_context_new();
1557 goto rdg_alloc_error;
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);
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)
1572 goto rdg_alloc_error;
1575 rdg->frontBio = BIO_new(BIO_s_rdg());
1578 goto rdg_alloc_error;
1580 rdg->frontBio->ptr = rdg;
1582 rdg->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1584 if (!rdg->readEvent)
1585 goto rdg_alloc_error;
1587 InitializeCriticalSection(&rdg->writeSection);
1597 void rdg_free(rdpRdg* rdg)
1604 tls_free(rdg->tlsOut);
1610 tls_free(rdg->tlsIn);
1616 http_context_free(rdg->http);
1622 ntlm_free(rdg->ntlm);
1628 CloseHandle(rdg->readEvent);
1629 rdg->readEvent = NULL;
1632 DeleteCriticalSection(&rdg->writeSection);