1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Terminal Server Gateway (TSG)
4  *
5  * Copyright 2012 Fujitsu Technology Solutions GmbH
6  * Copyright 2012 Dmitrij Jasnov <dmitrij.jasnov@ts.fujitsu.com>
7  * Copyright 2015 Thincast Technologies GmbH
8  * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <assert.h>
28 #include <winpr/crt.h>
29 #include <winpr/ndr.h>
30 #include <winpr/error.h>
31 #include <winpr/print.h>
32 #include <winpr/stream.h>
33 
34 #include <freerdp/log.h>
35 
36 #include "rpc_bind.h"
37 #include "rpc_client.h"
38 #include "tsg.h"
39 #include "../../crypto/opensslcompat.h"
40 
41 #define TAG FREERDP_TAG("core.gateway.tsg")
42 
43 #define TSG_CAPABILITY_TYPE_NAP 0x00000001
44 
45 #define TSG_PACKET_TYPE_HEADER 0x00004844
46 #define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643
47 #define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143
48 #define TSG_PACKET_TYPE_QUARREQUEST 0x00005152
49 #define TSG_PACKET_TYPE_RESPONSE 0x00005052
50 #define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552
51 #define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350
52 #define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752
53 #define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750
54 #define TSG_PACKET_TYPE_AUTH 0x00004054
55 #define TSG_PACKET_TYPE_REAUTH 0x00005250
56 
57 typedef WCHAR* RESOURCENAME;
58 
59 typedef struct _tsendpointinfo
60 {
61 	RESOURCENAME* resourceName;
62 	UINT32 numResourceNames;
63 	RESOURCENAME* alternateResourceNames;
64 	UINT16 numAlternateResourceNames;
65 	UINT32 Port;
66 } TSENDPOINTINFO, *PTSENDPOINTINFO;
67 
68 typedef struct _TSG_PACKET_HEADER
69 {
70 	UINT16 ComponentId;
71 	UINT16 PacketId;
72 } TSG_PACKET_HEADER, *PTSG_PACKET_HEADER;
73 
74 typedef struct _TSG_CAPABILITY_NAP
75 {
76 	UINT32 capabilities;
77 } TSG_CAPABILITY_NAP, *PTSG_CAPABILITY_NAP;
78 
79 typedef union
80 {
81 	TSG_CAPABILITY_NAP tsgCapNap;
82 } TSG_CAPABILITIES_UNION, *PTSG_CAPABILITIES_UNION;
83 
84 typedef struct _TSG_PACKET_CAPABILITIES
85 {
86 	UINT32 capabilityType;
87 	TSG_CAPABILITIES_UNION tsgPacket;
88 } TSG_PACKET_CAPABILITIES, *PTSG_PACKET_CAPABILITIES;
89 
90 typedef struct _TSG_PACKET_VERSIONCAPS
91 {
92 	TSG_PACKET_HEADER tsgHeader;
93 	PTSG_PACKET_CAPABILITIES tsgCaps;
94 	UINT32 numCapabilities;
95 	UINT16 majorVersion;
96 	UINT16 minorVersion;
97 	UINT16 quarantineCapabilities;
98 } TSG_PACKET_VERSIONCAPS, *PTSG_PACKET_VERSIONCAPS;
99 
100 typedef struct _TSG_PACKET_QUARCONFIGREQUEST
101 {
102 	UINT32 flags;
103 } TSG_PACKET_QUARCONFIGREQUEST, *PTSG_PACKET_QUARCONFIGREQUEST;
104 
105 typedef struct _TSG_PACKET_QUARREQUEST
106 {
107 	UINT32 flags;
108 	WCHAR* machineName;
109 	UINT32 nameLength;
110 	BYTE* data;
111 	UINT32 dataLen;
112 } TSG_PACKET_QUARREQUEST, *PTSG_PACKET_QUARREQUEST;
113 
114 typedef struct _TSG_REDIRECTION_FLAGS
115 {
116 	BOOL enableAllRedirections;
117 	BOOL disableAllRedirections;
118 	BOOL driveRedirectionDisabled;
119 	BOOL printerRedirectionDisabled;
120 	BOOL portRedirectionDisabled;
121 	BOOL reserved;
122 	BOOL clipboardRedirectionDisabled;
123 	BOOL pnpRedirectionDisabled;
124 } TSG_REDIRECTION_FLAGS, *PTSG_REDIRECTION_FLAGS;
125 
126 typedef struct _TSG_PACKET_RESPONSE
127 {
128 	UINT32 flags;
129 	UINT32 reserved;
130 	BYTE* responseData;
131 	UINT32 responseDataLen;
132 	TSG_REDIRECTION_FLAGS redirectionFlags;
133 } TSG_PACKET_RESPONSE, *PTSG_PACKET_RESPONSE;
134 
135 typedef struct _TSG_PACKET_QUARENC_RESPONSE
136 {
137 	UINT32 flags;
138 	UINT32 certChainLen;
139 	WCHAR* certChainData;
140 	GUID nonce;
141 	PTSG_PACKET_VERSIONCAPS versionCaps;
142 } TSG_PACKET_QUARENC_RESPONSE, *PTSG_PACKET_QUARENC_RESPONSE;
143 
144 typedef struct TSG_PACKET_STRING_MESSAGE
145 {
146 	INT32 isDisplayMandatory;
147 	INT32 isConsentMandatory;
148 	UINT32 msgBytes;
149 	WCHAR* msgBuffer;
150 } TSG_PACKET_STRING_MESSAGE;
151 
152 typedef struct TSG_PACKET_REAUTH_MESSAGE
153 {
154 	UINT64 tunnelContext;
155 } TSG_PACKET_REAUTH_MESSAGE, *PTSG_PACKET_REAUTH_MESSAGE;
156 
157 typedef struct _TSG_PACKET_MSG_RESPONSE
158 {
159 	UINT32 msgID;
160 	UINT32 msgType;
161 	INT32 isMsgPresent;
162 } TSG_PACKET_MSG_RESPONSE, *PTSG_PACKET_MSG_RESPONSE;
163 
164 typedef struct TSG_PACKET_CAPS_RESPONSE
165 {
166 	TSG_PACKET_QUARENC_RESPONSE pktQuarEncResponse;
167 	TSG_PACKET_MSG_RESPONSE pktConsentMessage;
168 } TSG_PACKET_CAPS_RESPONSE, *PTSG_PACKET_CAPS_RESPONSE;
169 
170 typedef struct TSG_PACKET_MSG_REQUEST
171 {
172 	UINT32 maxMessagesPerBatch;
173 } TSG_PACKET_MSG_REQUEST, *PTSG_PACKET_MSG_REQUEST;
174 
175 typedef struct _TSG_PACKET_AUTH
176 {
177 	TSG_PACKET_VERSIONCAPS tsgVersionCaps;
178 	UINT32 cookieLen;
179 	BYTE* cookie;
180 } TSG_PACKET_AUTH, *PTSG_PACKET_AUTH;
181 
182 typedef union
183 {
184 	PTSG_PACKET_VERSIONCAPS packetVersionCaps;
185 	PTSG_PACKET_AUTH packetAuth;
186 } TSG_INITIAL_PACKET_TYPE_UNION, *PTSG_INITIAL_PACKET_TYPE_UNION;
187 
188 typedef struct TSG_PACKET_REAUTH
189 {
190 	UINT64 tunnelContext;
191 	UINT32 packetId;
192 	TSG_INITIAL_PACKET_TYPE_UNION tsgInitialPacket;
193 } TSG_PACKET_REAUTH, *PTSG_PACKET_REAUTH;
194 
195 typedef union
196 {
197 	PTSG_PACKET_HEADER packetHeader;
198 	PTSG_PACKET_VERSIONCAPS packetVersionCaps;
199 	PTSG_PACKET_QUARCONFIGREQUEST packetQuarConfigRequest;
200 	PTSG_PACKET_QUARREQUEST packetQuarRequest;
201 	PTSG_PACKET_RESPONSE packetResponse;
202 	PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse;
203 	PTSG_PACKET_CAPS_RESPONSE packetCapsResponse;
204 	PTSG_PACKET_MSG_REQUEST packetMsgRequest;
205 	PTSG_PACKET_MSG_RESPONSE packetMsgResponse;
206 	PTSG_PACKET_AUTH packetAuth;
207 	PTSG_PACKET_REAUTH packetReauth;
208 } TSG_PACKET_TYPE_UNION;
209 
210 typedef struct _TSG_PACKET
211 {
212 	UINT32 packetId;
213 	TSG_PACKET_TYPE_UNION tsgPacket;
214 } TSG_PACKET, *PTSG_PACKET;
215 
216 struct rdp_tsg
217 {
218 	BIO* bio;
219 	rdpRpc* rpc;
220 	UINT16 Port;
221 	LPWSTR Hostname;
222 	LPWSTR MachineName;
223 	TSG_STATE state;
224 	UINT32 TunnelId;
225 	UINT32 ChannelId;
226 	BOOL reauthSequence;
227 	rdpTransport* transport;
228 	UINT64 ReauthTunnelContext;
229 	CONTEXT_HANDLE TunnelContext;
230 	CONTEXT_HANDLE ChannelContext;
231 	CONTEXT_HANDLE NewTunnelContext;
232 	CONTEXT_HANDLE NewChannelContext;
233 	TSG_PACKET_REAUTH packetReauth;
234 	TSG_PACKET_CAPABILITIES tsgCaps;
235 	TSG_PACKET_VERSIONCAPS packetVersionCaps;
236 };
237 
tsg_packet_id_to_string(UINT32 packetId)238 static const char* tsg_packet_id_to_string(UINT32 packetId)
239 {
240 	switch (packetId)
241 	{
242 		case TSG_PACKET_TYPE_HEADER:
243 			return "TSG_PACKET_TYPE_HEADER";
244 		case TSG_PACKET_TYPE_VERSIONCAPS:
245 			return "TSG_PACKET_TYPE_VERSIONCAPS";
246 		case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
247 			return "TSG_PACKET_TYPE_QUARCONFIGREQUEST";
248 		case TSG_PACKET_TYPE_QUARREQUEST:
249 			return "TSG_PACKET_TYPE_QUARREQUEST";
250 		case TSG_PACKET_TYPE_RESPONSE:
251 			return "TSG_PACKET_TYPE_RESPONSE";
252 		case TSG_PACKET_TYPE_QUARENC_RESPONSE:
253 			return "TSG_PACKET_TYPE_QUARENC_RESPONSE";
254 		case TSG_CAPABILITY_TYPE_NAP:
255 			return "TSG_CAPABILITY_TYPE_NAP";
256 		case TSG_PACKET_TYPE_CAPS_RESPONSE:
257 			return "TSG_PACKET_TYPE_CAPS_RESPONSE";
258 		case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
259 			return "TSG_PACKET_TYPE_MSGREQUEST_PACKET";
260 		case TSG_PACKET_TYPE_MESSAGE_PACKET:
261 			return "TSG_PACKET_TYPE_MESSAGE_PACKET";
262 		case TSG_PACKET_TYPE_AUTH:
263 			return "TSG_PACKET_TYPE_AUTH";
264 		case TSG_PACKET_TYPE_REAUTH:
265 			return "TSG_PACKET_TYPE_REAUTH";
266 		default:
267 			return "UNKNOWN";
268 	}
269 }
270 
tsg_state_to_string(TSG_STATE state)271 static const char* tsg_state_to_string(TSG_STATE state)
272 {
273 	switch (state)
274 	{
275 		case TSG_STATE_INITIAL:
276 			return "TSG_STATE_INITIAL";
277 		case TSG_STATE_CONNECTED:
278 			return "TSG_STATE_CONNECTED";
279 		case TSG_STATE_AUTHORIZED:
280 			return "TSG_STATE_AUTHORIZED";
281 		case TSG_STATE_CHANNEL_CREATED:
282 			return "TSG_STATE_CHANNEL_CREATED";
283 		case TSG_STATE_PIPE_CREATED:
284 			return "TSG_STATE_PIPE_CREATED";
285 		case TSG_STATE_TUNNEL_CLOSE_PENDING:
286 			return "TSG_STATE_TUNNEL_CLOSE_PENDING";
287 		case TSG_STATE_CHANNEL_CLOSE_PENDING:
288 			return "TSG_STATE_CHANNEL_CLOSE_PENDING";
289 		case TSG_STATE_FINAL:
290 			return "TSG_STATE_FINAL";
291 		default:
292 			return "TSG_STATE_UNKNOWN";
293 	}
294 }
295 
tsg_print(char ** buffer,size_t * len,const char * fmt,...)296 static BOOL tsg_print(char** buffer, size_t* len, const char* fmt, ...)
297 {
298 	int rc;
299 	va_list ap;
300 	if (!buffer || !len || !fmt)
301 		return FALSE;
302 	va_start(ap, fmt);
303 	rc = vsnprintf(*buffer, *len, fmt, ap);
304 	va_end(ap);
305 	if ((rc < 0) || ((size_t)rc > *len))
306 		return FALSE;
307 	*len -= (size_t)rc;
308 	*buffer += (size_t)rc;
309 	return TRUE;
310 }
311 
tsg_packet_header_to_string(char ** buffer,size_t * length,const TSG_PACKET_HEADER * header)312 static BOOL tsg_packet_header_to_string(char** buffer, size_t* length,
313                                         const TSG_PACKET_HEADER* header)
314 {
315 	assert(buffer);
316 	assert(length);
317 	assert(header);
318 
319 	return tsg_print(buffer, length,
320 	                 "header { ComponentId=0x%04" PRIx16 ", PacketId=0x%04" PRIx16 " }",
321 	                 header->ComponentId, header->PacketId);
322 }
323 
tsg_type_capability_nap_to_string(char ** buffer,size_t * length,const TSG_CAPABILITY_NAP * cur)324 static BOOL tsg_type_capability_nap_to_string(char** buffer, size_t* length,
325                                               const TSG_CAPABILITY_NAP* cur)
326 {
327 	assert(buffer);
328 	assert(length);
329 	assert(cur);
330 
331 	return tsg_print(buffer, length, "%s { capabilities=0x%08" PRIx32 " }",
332 	                 tsg_packet_id_to_string(TSG_CAPABILITY_TYPE_NAP), cur->capabilities);
333 }
334 
tsg_packet_capabilities_to_string(char ** buffer,size_t * length,const TSG_PACKET_CAPABILITIES * caps,UINT32 numCaps)335 static BOOL tsg_packet_capabilities_to_string(char** buffer, size_t* length,
336                                               const TSG_PACKET_CAPABILITIES* caps, UINT32 numCaps)
337 {
338 	UINT32 x;
339 
340 	assert(buffer);
341 	assert(length);
342 	assert(caps);
343 
344 	if (!tsg_print(buffer, length, "capabilities { "))
345 		return FALSE;
346 
347 	for (x = 0; x < numCaps; x++)
348 	{
349 		const TSG_PACKET_CAPABILITIES* cur = &caps[x];
350 		switch (cur->capabilityType)
351 		{
352 			case TSG_CAPABILITY_TYPE_NAP:
353 				if (!tsg_type_capability_nap_to_string(buffer, length, &cur->tsgPacket.tsgCapNap))
354 					return FALSE;
355 				break;
356 			default:
357 				if (!tsg_print(buffer, length, "TSG_UNKNOWN_CAPABILITY"))
358 					return FALSE;
359 				break;
360 		}
361 	}
362 	return tsg_print(buffer, length, " }");
363 }
364 
tsg_packet_versioncaps_to_string(char ** buffer,size_t * length,const TSG_PACKET_VERSIONCAPS * caps)365 static BOOL tsg_packet_versioncaps_to_string(char** buffer, size_t* length,
366                                              const TSG_PACKET_VERSIONCAPS* caps)
367 {
368 	assert(buffer);
369 	assert(length);
370 	assert(caps);
371 
372 	if (!tsg_print(buffer, length, "versioncaps { "))
373 		return FALSE;
374 	if (!tsg_packet_header_to_string(buffer, length, &caps->tsgHeader))
375 		return FALSE;
376 
377 	if (!tsg_print(buffer, length, " "))
378 		return FALSE;
379 
380 	if (!tsg_packet_capabilities_to_string(buffer, length, caps->tsgCaps, caps->numCapabilities))
381 		return FALSE;
382 
383 	if (!tsg_print(buffer, length,
384 	               " numCapabilities=0x%08" PRIx32 ", majorVersion=0x%04" PRIx16
385 	               ", minorVersion=0x%04" PRIx16 ", quarantineCapabilities=0x%04" PRIx16,
386 	               caps->numCapabilities, caps->majorVersion, caps->minorVersion,
387 	               caps->quarantineCapabilities))
388 		return FALSE;
389 
390 	return tsg_print(buffer, length, " }");
391 }
392 
tsg_packet_quarconfigrequest_to_string(char ** buffer,size_t * length,const TSG_PACKET_QUARCONFIGREQUEST * caps)393 static BOOL tsg_packet_quarconfigrequest_to_string(char** buffer, size_t* length,
394                                                    const TSG_PACKET_QUARCONFIGREQUEST* caps)
395 {
396 	assert(buffer);
397 	assert(length);
398 	assert(caps);
399 
400 	if (!tsg_print(buffer, length, "quarconfigrequest { "))
401 		return FALSE;
402 
403 	if (!tsg_print(buffer, length, " "))
404 		return FALSE;
405 
406 	if (!tsg_print(buffer, length, " flags=0x%08" PRIx32, caps->flags))
407 		return FALSE;
408 
409 	return tsg_print(buffer, length, " }");
410 }
411 
tsg_packet_quarrequest_to_string(char ** buffer,size_t * length,const TSG_PACKET_QUARREQUEST * caps)412 static BOOL tsg_packet_quarrequest_to_string(char** buffer, size_t* length,
413                                              const TSG_PACKET_QUARREQUEST* caps)
414 {
415 	BOOL rc = FALSE;
416 	char* name = NULL;
417 	char* strdata = NULL;
418 
419 	assert(buffer);
420 	assert(length);
421 	assert(caps);
422 
423 	if (!tsg_print(buffer, length, "quarrequest { "))
424 		return FALSE;
425 
426 	if (!tsg_print(buffer, length, " "))
427 		return FALSE;
428 
429 	if (caps->nameLength > 0)
430 	{
431 		if (caps->nameLength > INT_MAX)
432 			return FALSE;
433 		if (ConvertFromUnicode(CP_UTF8, 0, caps->machineName, (int)caps->nameLength, &name, 0, NULL,
434 		                       NULL) < 0)
435 			return FALSE;
436 	}
437 
438 	strdata = winpr_BinToHexString(caps->data, caps->dataLen, TRUE);
439 	if (strdata || (caps->dataLen == 0))
440 		rc = tsg_print(buffer, length,
441 		               " flags=0x%08" PRIx32 ", machineName=%s [%" PRIu32 "], data[%" PRIu32 "]=%s",
442 		               caps->flags, name, caps->nameLength, caps->dataLen, strdata);
443 	free(name);
444 	free(strdata);
445 	if (!rc)
446 		return FALSE;
447 
448 	return tsg_print(buffer, length, " }");
449 }
450 
tsg_bool_to_string(BOOL val)451 static const char* tsg_bool_to_string(BOOL val)
452 {
453 	if (val)
454 		return "true";
455 	return "false";
456 }
457 
tsg_redirection_flags_to_string(char * buffer,size_t size,const TSG_REDIRECTION_FLAGS * flags)458 static const char* tsg_redirection_flags_to_string(char* buffer, size_t size,
459                                                    const TSG_REDIRECTION_FLAGS* flags)
460 {
461 	assert(buffer || (size == 0));
462 	assert(flags);
463 
464 	_snprintf(buffer, size,
465 	          "enableAllRedirections=%s,  disableAllRedirections=%s, driveRedirectionDisabled=%s, "
466 	          "printerRedirectionDisabled=%s, portRedirectionDisabled=%s, reserved=%s, "
467 	          "clipboardRedirectionDisabled=%s, pnpRedirectionDisabled=%s",
468 	          tsg_bool_to_string(flags->enableAllRedirections),
469 	          tsg_bool_to_string(flags->disableAllRedirections),
470 	          tsg_bool_to_string(flags->driveRedirectionDisabled),
471 	          tsg_bool_to_string(flags->printerRedirectionDisabled),
472 	          tsg_bool_to_string(flags->portRedirectionDisabled),
473 	          tsg_bool_to_string(flags->reserved),
474 	          tsg_bool_to_string(flags->clipboardRedirectionDisabled),
475 	          tsg_bool_to_string(flags->pnpRedirectionDisabled));
476 	return buffer;
477 }
478 
tsg_packet_response_to_string(char ** buffer,size_t * length,const TSG_PACKET_RESPONSE * caps)479 static BOOL tsg_packet_response_to_string(char** buffer, size_t* length,
480                                           const TSG_PACKET_RESPONSE* caps)
481 {
482 	BOOL rc = FALSE;
483 	char* strdata = NULL;
484 	char tbuffer[8192] = { 0 };
485 
486 	assert(buffer);
487 	assert(length);
488 	assert(caps);
489 
490 	if (!tsg_print(buffer, length, "response { "))
491 		return FALSE;
492 
493 	if (!tsg_print(buffer, length, " "))
494 		return FALSE;
495 
496 	strdata = winpr_BinToHexString(caps->responseData, caps->responseDataLen, TRUE);
497 	if (strdata || (caps->responseDataLen == 0))
498 		rc = tsg_print(
499 		    buffer, length,
500 		    " flags=0x%08" PRIx32 ", reserved=0x%08" PRIx32 ", responseData[%" PRIu32
501 		    "]=%s, redirectionFlags={ %s }",
502 		    caps->flags, caps->reserved, caps->responseDataLen, strdata,
503 		    tsg_redirection_flags_to_string(tbuffer, ARRAYSIZE(tbuffer), &caps->redirectionFlags));
504 	free(strdata);
505 	if (!rc)
506 		return FALSE;
507 
508 	return tsg_print(buffer, length, " }");
509 }
510 
tsg_packet_quarenc_response_to_string(char ** buffer,size_t * length,const TSG_PACKET_QUARENC_RESPONSE * caps)511 static BOOL tsg_packet_quarenc_response_to_string(char** buffer, size_t* length,
512                                                   const TSG_PACKET_QUARENC_RESPONSE* caps)
513 {
514 	BOOL rc = FALSE;
515 	char* strdata = NULL;
516 	RPC_CSTR uuid;
517 	char tbuffer[8192] = { 0 };
518 	size_t size = ARRAYSIZE(tbuffer);
519 	char* ptbuffer = tbuffer;
520 
521 	assert(buffer);
522 	assert(length);
523 	assert(caps);
524 
525 	if (!tsg_print(buffer, length, "quarenc_response { "))
526 		return FALSE;
527 
528 	if (!tsg_print(buffer, length, " "))
529 		return FALSE;
530 
531 	if (caps->certChainLen > 0)
532 	{
533 		if (caps->certChainLen > INT_MAX)
534 			return FALSE;
535 		if (ConvertFromUnicode(CP_UTF8, 0, caps->certChainData, (int)caps->certChainLen, &strdata,
536 		                       0, NULL, NULL) <= 0)
537 			return FALSE;
538 	}
539 
540 	tsg_packet_versioncaps_to_string(&ptbuffer, &size, caps->versionCaps);
541 	UuidToStringA(&caps->nonce, &uuid);
542 	if (strdata || (caps->certChainLen == 0))
543 		rc =
544 		    tsg_print(buffer, length,
545 		              " flags=0x%08" PRIx32 ", certChain[%" PRIu32 "]=%s, nonce=%s, versionCaps=%s",
546 		              caps->flags, caps->certChainLen, strdata, uuid, tbuffer);
547 	free(strdata);
548 	free(uuid);
549 	if (!rc)
550 		return FALSE;
551 
552 	return tsg_print(buffer, length, " }");
553 }
554 
tsg_packet_message_response_to_string(char ** buffer,size_t * length,const TSG_PACKET_MSG_RESPONSE * caps)555 static BOOL tsg_packet_message_response_to_string(char** buffer, size_t* length,
556                                                   const TSG_PACKET_MSG_RESPONSE* caps)
557 {
558 	assert(buffer);
559 	assert(length);
560 	assert(caps);
561 
562 	if (!tsg_print(buffer, length, "msg_response { "))
563 		return FALSE;
564 
565 	if (!tsg_print(buffer, length,
566 	               " msgID=0x%08" PRIx32 ", msgType=0x%08" PRIx32 ", isMsgPresent=%" PRId32,
567 	               caps->msgID, caps->msgType, caps->isMsgPresent))
568 		return FALSE;
569 
570 	return tsg_print(buffer, length, " }");
571 }
572 
tsg_packet_caps_response_to_string(char ** buffer,size_t * length,const TSG_PACKET_CAPS_RESPONSE * caps)573 static BOOL tsg_packet_caps_response_to_string(char** buffer, size_t* length,
574                                                const TSG_PACKET_CAPS_RESPONSE* caps)
575 {
576 	assert(buffer);
577 	assert(length);
578 	assert(caps);
579 
580 	if (!tsg_print(buffer, length, "caps_response { "))
581 		return FALSE;
582 
583 	if (!tsg_packet_quarenc_response_to_string(buffer, length, &caps->pktQuarEncResponse))
584 		return FALSE;
585 
586 	if (!tsg_packet_message_response_to_string(buffer, length, &caps->pktConsentMessage))
587 		return FALSE;
588 
589 	return tsg_print(buffer, length, " }");
590 }
591 
tsg_packet_message_request_to_string(char ** buffer,size_t * length,const TSG_PACKET_MSG_REQUEST * caps)592 static BOOL tsg_packet_message_request_to_string(char** buffer, size_t* length,
593                                                  const TSG_PACKET_MSG_REQUEST* caps)
594 {
595 	assert(buffer);
596 	assert(length);
597 	assert(caps);
598 
599 	if (!tsg_print(buffer, length, "caps_message_request { "))
600 		return FALSE;
601 
602 	if (!tsg_print(buffer, length, " maxMessagesPerBatch=%" PRIu32, caps->maxMessagesPerBatch))
603 		return FALSE;
604 
605 	return tsg_print(buffer, length, " }");
606 }
607 
tsg_packet_auth_to_string(char ** buffer,size_t * length,const TSG_PACKET_AUTH * caps)608 static BOOL tsg_packet_auth_to_string(char** buffer, size_t* length, const TSG_PACKET_AUTH* caps)
609 {
610 	BOOL rc = FALSE;
611 	char* strdata = NULL;
612 	assert(buffer);
613 	assert(length);
614 	assert(caps);
615 
616 	if (!tsg_print(buffer, length, "caps_message_request { "))
617 		return FALSE;
618 
619 	if (!tsg_packet_versioncaps_to_string(buffer, length, &caps->tsgVersionCaps))
620 		return FALSE;
621 
622 	strdata = winpr_BinToHexString(caps->cookie, caps->cookieLen, TRUE);
623 	if (strdata || (caps->cookieLen == 0))
624 		rc = tsg_print(buffer, length, " cookie[%" PRIu32 "]=%s", caps->cookieLen, strdata);
625 	free(strdata);
626 	if (!rc)
627 		return FALSE;
628 
629 	return tsg_print(buffer, length, " }");
630 }
631 
tsg_packet_reauth_to_string(char ** buffer,size_t * length,const TSG_PACKET_REAUTH * caps)632 static BOOL tsg_packet_reauth_to_string(char** buffer, size_t* length,
633                                         const TSG_PACKET_REAUTH* caps)
634 {
635 	BOOL rc = FALSE;
636 	assert(buffer);
637 	assert(length);
638 	assert(caps);
639 
640 	if (!tsg_print(buffer, length, "caps_message_request { "))
641 		return FALSE;
642 
643 	if (!tsg_print(buffer, length, " tunnelContext=0x%016" PRIx64 ", packetId=%s [0x%08" PRIx32 "]",
644 	               caps->tunnelContext, tsg_packet_id_to_string(caps->packetId), caps->packetId))
645 		return FALSE;
646 
647 	switch (caps->packetId)
648 	{
649 		case TSG_PACKET_TYPE_VERSIONCAPS:
650 			rc = tsg_packet_versioncaps_to_string(buffer, length,
651 			                                      caps->tsgInitialPacket.packetVersionCaps);
652 			break;
653 		case TSG_PACKET_TYPE_AUTH:
654 			rc = tsg_packet_auth_to_string(buffer, length, caps->tsgInitialPacket.packetAuth);
655 			break;
656 		default:
657 			rc = tsg_print(buffer, length, "TODO: Unhandled packet type %s [0x%08" PRIx32 "]",
658 			               tsg_packet_id_to_string(caps->packetId), caps->packetId);
659 			break;
660 	}
661 
662 	if (!rc)
663 		return FALSE;
664 
665 	return tsg_print(buffer, length, " }");
666 }
667 
tsg_packet_to_string(const TSG_PACKET * packet)668 static const char* tsg_packet_to_string(const TSG_PACKET* packet)
669 {
670 	size_t len = 8192;
671 	static char sbuffer[8193] = { 0 };
672 	char* buffer = sbuffer;
673 
674 	if (!tsg_print(&buffer, &len, "TSG_PACKET { packetId=%s [0x%08" PRIx32 "], ",
675 	               tsg_packet_id_to_string(packet->packetId), packet->packetId))
676 		goto fail;
677 
678 	switch (packet->packetId)
679 	{
680 		case TSG_PACKET_TYPE_HEADER:
681 			if (!tsg_packet_header_to_string(&buffer, &len, packet->tsgPacket.packetHeader))
682 				goto fail;
683 			break;
684 		case TSG_PACKET_TYPE_VERSIONCAPS:
685 			if (!tsg_packet_versioncaps_to_string(&buffer, &len,
686 			                                      packet->tsgPacket.packetVersionCaps))
687 				goto fail;
688 			break;
689 		case TSG_PACKET_TYPE_QUARCONFIGREQUEST:
690 			if (!tsg_packet_quarconfigrequest_to_string(&buffer, &len,
691 			                                            packet->tsgPacket.packetQuarConfigRequest))
692 				goto fail;
693 			break;
694 		case TSG_PACKET_TYPE_QUARREQUEST:
695 			if (!tsg_packet_quarrequest_to_string(&buffer, &len,
696 			                                      packet->tsgPacket.packetQuarRequest))
697 				goto fail;
698 			break;
699 		case TSG_PACKET_TYPE_RESPONSE:
700 			if (!tsg_packet_response_to_string(&buffer, &len, packet->tsgPacket.packetResponse))
701 				goto fail;
702 			break;
703 		case TSG_PACKET_TYPE_QUARENC_RESPONSE:
704 			if (!tsg_packet_quarenc_response_to_string(&buffer, &len,
705 			                                           packet->tsgPacket.packetQuarEncResponse))
706 				goto fail;
707 			break;
708 		case TSG_PACKET_TYPE_CAPS_RESPONSE:
709 			if (!tsg_packet_caps_response_to_string(&buffer, &len,
710 			                                        packet->tsgPacket.packetCapsResponse))
711 				goto fail;
712 			break;
713 		case TSG_PACKET_TYPE_MSGREQUEST_PACKET:
714 			if (!tsg_packet_message_request_to_string(&buffer, &len,
715 			                                          packet->tsgPacket.packetMsgRequest))
716 				goto fail;
717 			break;
718 		case TSG_PACKET_TYPE_MESSAGE_PACKET:
719 			if (!tsg_packet_message_response_to_string(&buffer, &len,
720 			                                           packet->tsgPacket.packetMsgResponse))
721 				goto fail;
722 			break;
723 		case TSG_PACKET_TYPE_AUTH:
724 			if (!tsg_packet_auth_to_string(&buffer, &len, packet->tsgPacket.packetAuth))
725 				goto fail;
726 			break;
727 		case TSG_PACKET_TYPE_REAUTH:
728 			if (!tsg_packet_reauth_to_string(&buffer, &len, packet->tsgPacket.packetReauth))
729 				goto fail;
730 			break;
731 		default:
732 			if (!tsg_print(&buffer, &len, "INVALID"))
733 				goto fail;
734 			break;
735 	}
736 
737 	if (!tsg_print(&buffer, &len, " }"))
738 		goto fail;
739 
740 fail:
741 	return sbuffer;
742 }
743 
tsg_stream_align(wStream * s,size_t align)744 static BOOL tsg_stream_align(wStream* s, size_t align)
745 {
746 	size_t pos;
747 	size_t offset = 0;
748 
749 	if (!s)
750 		return FALSE;
751 
752 	pos = Stream_GetPosition(s);
753 
754 	if ((pos % align) != 0)
755 		offset = align - pos % align;
756 
757 	return Stream_SafeSeek(s, offset);
758 }
759 
760 static BIO_METHOD* BIO_s_tsg(void);
761 /**
762  * RPC Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378623/
763  * Remote Procedure Call: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378651/
764  * RPC NDR Interface Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/hh802752/
765  */
766 
767 /**
768  * call sequence with silent reauth:
769  *
770  * TsProxyCreateTunnelRequest()
771  * TsProxyCreateTunnelResponse(TunnelContext)
772  * TsProxyAuthorizeTunnelRequest(TunnelContext)
773  * TsProxyAuthorizeTunnelResponse()
774  * TsProxyMakeTunnelCallRequest(TunnelContext)
775  * TsProxyCreateChannelRequest(TunnelContext)
776  * TsProxyCreateChannelResponse(ChannelContext)
777  * TsProxySetupReceivePipeRequest(ChannelContext)
778  * TsProxySendToServerRequest(ChannelContext)
779  *
780  * ...
781  *
782  * TsProxyMakeTunnelCallResponse(reauth)
783  * TsProxyCreateTunnelRequest()
784  * TsProxyMakeTunnelCallRequest(TunnelContext)
785  * TsProxyCreateTunnelResponse(NewTunnelContext)
786  * TsProxyAuthorizeTunnelRequest(NewTunnelContext)
787  * TsProxyAuthorizeTunnelResponse()
788  * TsProxyCreateChannelRequest(NewTunnelContext)
789  * TsProxyCreateChannelResponse(NewChannelContext)
790  * TsProxyCloseChannelRequest(NewChannelContext)
791  * TsProxyCloseTunnelRequest(NewTunnelContext)
792  * TsProxyCloseChannelResponse(NullChannelContext)
793  * TsProxyCloseTunnelResponse(NullTunnelContext)
794  * TsProxySendToServerRequest(ChannelContext)
795  */
796 
TsProxySendToServer(handle_t IDL_handle,const byte pRpcMessage[],UINT32 count,UINT32 * lengths)797 static int TsProxySendToServer(handle_t IDL_handle, const byte pRpcMessage[], UINT32 count,
798                                UINT32* lengths)
799 {
800 	wStream* s;
801 	rdpTsg* tsg;
802 	size_t length;
803 	const byte* buffer1 = NULL;
804 	const byte* buffer2 = NULL;
805 	const byte* buffer3 = NULL;
806 	UINT32 buffer1Length;
807 	UINT32 buffer2Length;
808 	UINT32 buffer3Length;
809 	UINT32 numBuffers = 0;
810 	UINT32 totalDataBytes = 0;
811 	tsg = (rdpTsg*)IDL_handle;
812 	buffer1Length = buffer2Length = buffer3Length = 0;
813 
814 	if (count > 0)
815 	{
816 		numBuffers++;
817 		buffer1 = &pRpcMessage[0];
818 		buffer1Length = lengths[0];
819 		totalDataBytes += lengths[0] + 4;
820 	}
821 
822 	if (count > 1)
823 	{
824 		numBuffers++;
825 		buffer2 = &pRpcMessage[1];
826 		buffer2Length = lengths[1];
827 		totalDataBytes += lengths[1] + 4;
828 	}
829 
830 	if (count > 2)
831 	{
832 		numBuffers++;
833 		buffer3 = &pRpcMessage[2];
834 		buffer3Length = lengths[2];
835 		totalDataBytes += lengths[2] + 4;
836 	}
837 
838 	length = 28ull + totalDataBytes;
839 	if (length > INT_MAX)
840 		return -1;
841 	s = Stream_New(NULL, length);
842 
843 	if (!s)
844 	{
845 		WLog_ERR(TAG, "Stream_New failed!");
846 		return -1;
847 	}
848 
849 	/* PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE_NR (20 bytes) */
850 	Stream_Write(s, &tsg->ChannelContext.ContextType, 4); /* ContextType (4 bytes) */
851 	Stream_Write(s, tsg->ChannelContext.ContextUuid, 16); /* ContextUuid (16 bytes) */
852 	Stream_Write_UINT32_BE(s, totalDataBytes);            /* totalDataBytes (4 bytes) */
853 	Stream_Write_UINT32_BE(s, numBuffers);                /* numBuffers (4 bytes) */
854 
855 	if (buffer1Length > 0)
856 		Stream_Write_UINT32_BE(s, buffer1Length); /* buffer1Length (4 bytes) */
857 
858 	if (buffer2Length > 0)
859 		Stream_Write_UINT32_BE(s, buffer2Length); /* buffer2Length (4 bytes) */
860 
861 	if (buffer3Length > 0)
862 		Stream_Write_UINT32_BE(s, buffer3Length); /* buffer3Length (4 bytes) */
863 
864 	if (buffer1Length > 0)
865 		Stream_Write(s, buffer1, buffer1Length); /* buffer1 (variable) */
866 
867 	if (buffer2Length > 0)
868 		Stream_Write(s, buffer2, buffer2Length); /* buffer2 (variable) */
869 
870 	if (buffer3Length > 0)
871 		Stream_Write(s, buffer3, buffer3Length); /* buffer3 (variable) */
872 
873 	if (!rpc_client_write_call(tsg->rpc, s, TsProxySendToServerOpnum))
874 		return -1;
875 
876 	return (int)length;
877 }
878 
879 /**
880  * OpNum = 1
881  *
882  * HRESULT TsProxyCreateTunnel(
883  * [in, ref] PTSG_PACKET tsgPacket,
884  * [out, ref] PTSG_PACKET* tsgPacketResponse,
885  * [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext,
886  * [out] unsigned long* tunnelId
887  * );
888  */
889 
TsProxyCreateTunnelWriteRequest(rdpTsg * tsg,const PTSG_PACKET tsgPacket)890 static BOOL TsProxyCreateTunnelWriteRequest(rdpTsg* tsg, const PTSG_PACKET tsgPacket)
891 {
892 	BOOL rc = FALSE;
893 	BOOL write = TRUE;
894 	UINT16 opnum = 0;
895 	wStream* s;
896 	rdpRpc* rpc;
897 
898 	if (!tsg || !tsg->rpc)
899 		return FALSE;
900 
901 	rpc = tsg->rpc;
902 	WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_to_string(tsgPacket));
903 	s = Stream_New(NULL, 108);
904 
905 	if (!s)
906 		return FALSE;
907 
908 	switch (tsgPacket->packetId)
909 	{
910 		case TSG_PACKET_TYPE_VERSIONCAPS:
911 		{
912 			PTSG_PACKET_VERSIONCAPS packetVersionCaps = tsgPacket->tsgPacket.packetVersionCaps;
913 			PTSG_CAPABILITY_NAP tsgCapNap = &packetVersionCaps->tsgCaps->tsgPacket.tsgCapNap;
914 			Stream_Write_UINT32(s, tsgPacket->packetId); /* PacketId (4 bytes) */
915 			Stream_Write_UINT32(s, tsgPacket->packetId); /* SwitchValue (4 bytes) */
916 			Stream_Write_UINT32(s, 0x00020000);          /* PacketVersionCapsPtr (4 bytes) */
917 			Stream_Write_UINT16(
918 			    s, packetVersionCaps->tsgHeader.ComponentId); /* ComponentId (2 bytes) */
919 			Stream_Write_UINT16(s, packetVersionCaps->tsgHeader.PacketId); /* PacketId (2 bytes) */
920 			Stream_Write_UINT32(s, 0x00020004); /* TsgCapsPtr (4 bytes) */
921 			Stream_Write_UINT32(s,
922 			                    packetVersionCaps->numCapabilities); /* NumCapabilities (4 bytes) */
923 			Stream_Write_UINT16(s, packetVersionCaps->majorVersion); /* MajorVersion (2 bytes) */
924 			Stream_Write_UINT16(s, packetVersionCaps->minorVersion); /* MinorVersion (2 bytes) */
925 			Stream_Write_UINT16(
926 			    s,
927 			    packetVersionCaps->quarantineCapabilities); /* QuarantineCapabilities (2 bytes) */
928 			/* 4-byte alignment (30 + 2) */
929 			Stream_Write_UINT16(s, 0x0000);                             /* pad (2 bytes) */
930 			Stream_Write_UINT32(s, packetVersionCaps->numCapabilities); /* MaxCount (4 bytes) */
931 			Stream_Write_UINT32(
932 			    s, packetVersionCaps->tsgCaps->capabilityType); /* CapabilityType (4 bytes) */
933 			Stream_Write_UINT32(
934 			    s, packetVersionCaps->tsgCaps->capabilityType); /* SwitchValue (4 bytes) */
935 			Stream_Write_UINT32(s, tsgCapNap->capabilities);    /* capabilities (4 bytes) */
936 			/**
937 			 * The following 60-byte structure is apparently undocumented,
938 			 * but parts of it can be matched to known C706 data structures.
939 			 */
940 			/*
941 			 * 8-byte constant (8A E3 13 71 02 F4 36 71) also observed here:
942 			 * http://lists.samba.org/archive/cifs-protocol/2010-July/001543.html
943 			 */
944 			Stream_Write_UINT8(s, 0x8A);
945 			Stream_Write_UINT8(s, 0xE3);
946 			Stream_Write_UINT8(s, 0x13);
947 			Stream_Write_UINT8(s, 0x71);
948 			Stream_Write_UINT8(s, 0x02);
949 			Stream_Write_UINT8(s, 0xF4);
950 			Stream_Write_UINT8(s, 0x36);
951 			Stream_Write_UINT8(s, 0x71);
952 			Stream_Write_UINT32(s, 0x00040001); /* 1.4 (version?) */
953 			Stream_Write_UINT32(s, 0x00000001); /* 1 (element count?) */
954 			/* p_cont_list_t */
955 			Stream_Write_UINT8(s, 2);       /* ncontext_elem */
956 			Stream_Write_UINT8(s, 0x40);    /* reserved1 */
957 			Stream_Write_UINT16(s, 0x0028); /* reserved2 */
958 			/* p_syntax_id_t */
959 			Stream_Write(s, &TSGU_UUID, sizeof(p_uuid_t));
960 			Stream_Write_UINT32(s, TSGU_SYNTAX_IF_VERSION);
961 			/* p_syntax_id_t */
962 			Stream_Write(s, &NDR_UUID, sizeof(p_uuid_t));
963 			Stream_Write_UINT32(s, NDR_SYNTAX_IF_VERSION);
964 			opnum = TsProxyCreateTunnelOpnum;
965 		}
966 		break;
967 
968 		case TSG_PACKET_TYPE_REAUTH:
969 		{
970 			PTSG_PACKET_REAUTH packetReauth = tsgPacket->tsgPacket.packetReauth;
971 			PTSG_PACKET_VERSIONCAPS packetVersionCaps =
972 			    packetReauth->tsgInitialPacket.packetVersionCaps;
973 			PTSG_CAPABILITY_NAP tsgCapNap = &packetVersionCaps->tsgCaps->tsgPacket.tsgCapNap;
974 			Stream_Write_UINT32(s, tsgPacket->packetId);         /* PacketId (4 bytes) */
975 			Stream_Write_UINT32(s, tsgPacket->packetId);         /* SwitchValue (4 bytes) */
976 			Stream_Write_UINT32(s, 0x00020000);                  /* PacketReauthPtr (4 bytes) */
977 			Stream_Write_UINT32(s, 0);                           /* ??? (4 bytes) */
978 			Stream_Write_UINT64(s, packetReauth->tunnelContext); /* TunnelContext (8 bytes) */
979 			Stream_Write_UINT32(s, TSG_PACKET_TYPE_VERSIONCAPS); /* PacketId (4 bytes) */
980 			Stream_Write_UINT32(s, TSG_PACKET_TYPE_VERSIONCAPS); /* SwitchValue (4 bytes) */
981 			Stream_Write_UINT32(s, 0x00020004); /* PacketVersionCapsPtr (4 bytes) */
982 			Stream_Write_UINT16(
983 			    s, packetVersionCaps->tsgHeader.ComponentId); /* ComponentId (2 bytes) */
984 			Stream_Write_UINT16(s, packetVersionCaps->tsgHeader.PacketId); /* PacketId (2 bytes) */
985 			Stream_Write_UINT32(s, 0x00020008); /* TsgCapsPtr (4 bytes) */
986 			Stream_Write_UINT32(s,
987 			                    packetVersionCaps->numCapabilities); /* NumCapabilities (4 bytes) */
988 			Stream_Write_UINT16(s, packetVersionCaps->majorVersion); /* MajorVersion (2 bytes) */
989 			Stream_Write_UINT16(s, packetVersionCaps->minorVersion); /* MinorVersion (2 bytes) */
990 			Stream_Write_UINT16(
991 			    s,
992 			    packetVersionCaps->quarantineCapabilities); /* QuarantineCapabilities (2 bytes) */
993 			/* 4-byte alignment (30 + 2) */
994 			Stream_Write_UINT16(s, 0x0000);                             /* pad (2 bytes) */
995 			Stream_Write_UINT32(s, packetVersionCaps->numCapabilities); /* MaxCount (4 bytes) */
996 			Stream_Write_UINT32(
997 			    s, packetVersionCaps->tsgCaps->capabilityType); /* CapabilityType (4 bytes) */
998 			Stream_Write_UINT32(
999 			    s, packetVersionCaps->tsgCaps->capabilityType); /* SwitchValue (4 bytes) */
1000 			Stream_Write_UINT32(s, tsgCapNap->capabilities);    /* capabilities (4 bytes) */
1001 			opnum = TsProxyCreateTunnelOpnum;
1002 		}
1003 		break;
1004 
1005 		default:
1006 			write = FALSE;
1007 			break;
1008 	}
1009 
1010 	rc = TRUE;
1011 
1012 	if (write)
1013 		return rpc_client_write_call(rpc, s, opnum);
1014 
1015 	Stream_Free(s, TRUE);
1016 	return rc;
1017 }
1018 
TsProxyCreateTunnelReadResponse(rdpTsg * tsg,RPC_PDU * pdu,CONTEXT_HANDLE * tunnelContext,UINT32 * tunnelId)1019 static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
1020                                             CONTEXT_HANDLE* tunnelContext, UINT32* tunnelId)
1021 {
1022 	BOOL rc = FALSE;
1023 	UINT32 count;
1024 	UINT32 Pointer;
1025 	PTSG_PACKET packet;
1026 	UINT32 SwitchValue;
1027 	UINT32 MessageSwitchValue = 0;
1028 	UINT32 IsMessagePresent;
1029 	rdpContext* context;
1030 	PTSG_PACKET_CAPABILITIES tsgCaps = NULL;
1031 	PTSG_PACKET_VERSIONCAPS versionCaps = NULL;
1032 	TSG_PACKET_STRING_MESSAGE packetStringMessage;
1033 	PTSG_PACKET_CAPS_RESPONSE packetCapsResponse = NULL;
1034 	PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse = NULL;
1035 
1036 	assert(tsg);
1037 	assert(tsg->rpc);
1038 
1039 	context = tsg->rpc->context;
1040 	assert(context);
1041 
1042 	if (!pdu)
1043 		return FALSE;
1044 
1045 	packet = (PTSG_PACKET)calloc(1, sizeof(TSG_PACKET));
1046 
1047 	if (!packet)
1048 		return FALSE;
1049 
1050 	if (Stream_GetRemainingLength(pdu->s) < 12)
1051 		goto fail;
1052 
1053 	Stream_Seek_UINT32(pdu->s);                   /* PacketPtr (4 bytes) */
1054 	Stream_Read_UINT32(pdu->s, packet->packetId); /* PacketId (4 bytes) */
1055 	Stream_Read_UINT32(pdu->s, SwitchValue);      /* SwitchValue (4 bytes) */
1056 
1057 	WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet->packetId));
1058 
1059 	if ((packet->packetId == TSG_PACKET_TYPE_CAPS_RESPONSE) &&
1060 	    (SwitchValue == TSG_PACKET_TYPE_CAPS_RESPONSE))
1061 	{
1062 		packetCapsResponse = (PTSG_PACKET_CAPS_RESPONSE)calloc(1, sizeof(TSG_PACKET_CAPS_RESPONSE));
1063 
1064 		if (!packetCapsResponse)
1065 			goto fail;
1066 
1067 		packet->tsgPacket.packetCapsResponse = packetCapsResponse;
1068 
1069 		if (Stream_GetRemainingLength(pdu->s) < 32)
1070 			goto fail;
1071 
1072 		Stream_Seek_UINT32(pdu->s); /* PacketQuarResponsePtr (4 bytes) */
1073 		Stream_Read_UINT32(pdu->s,
1074 		                   packetCapsResponse->pktQuarEncResponse.flags); /* Flags (4 bytes) */
1075 		Stream_Read_UINT32(
1076 		    pdu->s,
1077 		    packetCapsResponse->pktQuarEncResponse.certChainLen); /* CertChainLength (4 bytes) */
1078 		Stream_Seek_UINT32(pdu->s);                               /* CertChainDataPtr (4 bytes) */
1079 		Stream_Read(pdu->s, &packetCapsResponse->pktQuarEncResponse.nonce,
1080 		            16);                     /* Nonce (16 bytes) */
1081 		Stream_Read_UINT32(pdu->s, Pointer); /* VersionCapsPtr (4 bytes) */
1082 
1083 		if ((Pointer == 0x0002000C) || (Pointer == 0x00020008))
1084 		{
1085 			if (Stream_GetRemainingLength(pdu->s) < 16)
1086 				goto fail;
1087 
1088 			Stream_Seek_UINT32(pdu->s);                     /* MsgId (4 bytes) */
1089 			Stream_Seek_UINT32(pdu->s);                     /* MsgType (4 bytes) */
1090 			Stream_Read_UINT32(pdu->s, IsMessagePresent);   /* IsMessagePresent (4 bytes) */
1091 			Stream_Read_UINT32(pdu->s, MessageSwitchValue); /* MessageSwitchValue (4 bytes) */
1092 		}
1093 
1094 		if (packetCapsResponse->pktQuarEncResponse.certChainLen > 0)
1095 		{
1096 			if (Stream_GetRemainingLength(pdu->s) < 16)
1097 				goto fail;
1098 
1099 			Stream_Read_UINT32(pdu->s, Pointer); /* MsgPtr (4 bytes): 0x00020014 */
1100 			Stream_Seek_UINT32(pdu->s);          /* MaxCount (4 bytes) */
1101 			Stream_Seek_UINT32(pdu->s);          /* Offset (4 bytes) */
1102 			Stream_Read_UINT32(pdu->s, count);   /* ActualCount (4 bytes) */
1103 
1104 			/*
1105 			 * CertChainData is a wide character string, and the count is
1106 			 * given in characters excluding the null terminator, therefore:
1107 			 * size = (count * 2)
1108 			 */
1109 			if (!Stream_SafeSeek(pdu->s, count * 2)) /* CertChainData */
1110 				goto fail;
1111 
1112 			/* 4-byte alignment */
1113 			if (!tsg_stream_align(pdu->s, 4))
1114 				goto fail;
1115 		}
1116 		else
1117 		{
1118 			if (Stream_GetRemainingLength(pdu->s) < 4)
1119 				goto fail;
1120 
1121 			Stream_Read_UINT32(pdu->s, Pointer); /* Ptr (4 bytes) */
1122 		}
1123 
1124 		versionCaps = (PTSG_PACKET_VERSIONCAPS)calloc(1, sizeof(TSG_PACKET_VERSIONCAPS));
1125 
1126 		if (!versionCaps)
1127 			goto fail;
1128 
1129 		packetCapsResponse->pktQuarEncResponse.versionCaps = versionCaps;
1130 
1131 		if (Stream_GetRemainingLength(pdu->s) < 18)
1132 			goto fail;
1133 
1134 		Stream_Read_UINT16(pdu->s, versionCaps->tsgHeader.ComponentId); /* ComponentId (2 bytes) */
1135 		Stream_Read_UINT16(pdu->s, versionCaps->tsgHeader.PacketId);    /* PacketId (2 bytes) */
1136 
1137 		if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT)
1138 		{
1139 			WLog_ERR(TAG, "Unexpected ComponentId: 0x%04" PRIX16 ", Expected TS_GATEWAY_TRANSPORT",
1140 			         versionCaps->tsgHeader.ComponentId);
1141 			goto fail;
1142 		}
1143 
1144 		Stream_Read_UINT32(pdu->s, Pointer);                      /* TsgCapsPtr (4 bytes) */
1145 		Stream_Read_UINT32(pdu->s, versionCaps->numCapabilities); /* NumCapabilities (4 bytes) */
1146 		Stream_Read_UINT16(pdu->s, versionCaps->majorVersion);    /* MajorVersion (2 bytes) */
1147 		Stream_Read_UINT16(pdu->s, versionCaps->minorVersion);    /* MinorVersion (2 bytes) */
1148 		Stream_Read_UINT16(
1149 		    pdu->s, versionCaps->quarantineCapabilities); /* QuarantineCapabilities (2 bytes) */
1150 
1151 		/* 4-byte alignment */
1152 		if (!tsg_stream_align(pdu->s, 4))
1153 			goto fail;
1154 
1155 		tsgCaps = (PTSG_PACKET_CAPABILITIES)calloc(1, sizeof(TSG_PACKET_CAPABILITIES));
1156 
1157 		if (!tsgCaps)
1158 			goto fail;
1159 
1160 		versionCaps->tsgCaps = tsgCaps;
1161 
1162 		if (Stream_GetRemainingLength(pdu->s) < 16)
1163 			goto fail;
1164 
1165 		Stream_Seek_UINT32(pdu->s);                          /* MaxCount (4 bytes) */
1166 		Stream_Read_UINT32(pdu->s, tsgCaps->capabilityType); /* CapabilityType (4 bytes) */
1167 		Stream_Read_UINT32(pdu->s, SwitchValue);             /* SwitchValue (4 bytes) */
1168 
1169 		if ((SwitchValue != TSG_CAPABILITY_TYPE_NAP) ||
1170 		    (tsgCaps->capabilityType != TSG_CAPABILITY_TYPE_NAP))
1171 		{
1172 			WLog_ERR(TAG,
1173 			         "Unexpected CapabilityType: 0x%08" PRIX32 ", Expected TSG_CAPABILITY_TYPE_NAP",
1174 			         tsgCaps->capabilityType);
1175 			goto fail;
1176 		}
1177 
1178 		Stream_Read_UINT32(pdu->s,
1179 		                   tsgCaps->tsgPacket.tsgCapNap.capabilities); /* Capabilities (4 bytes) */
1180 
1181 		switch (MessageSwitchValue)
1182 		{
1183 			case TSG_ASYNC_MESSAGE_CONSENT_MESSAGE:
1184 			case TSG_ASYNC_MESSAGE_SERVICE_MESSAGE:
1185 				if (Stream_GetRemainingLength(pdu->s) < 16)
1186 					goto fail;
1187 
1188 				Stream_Read_INT32(pdu->s, packetStringMessage.isDisplayMandatory);
1189 				Stream_Read_INT32(pdu->s, packetStringMessage.isConsentMandatory);
1190 				Stream_Read_UINT32(pdu->s, packetStringMessage.msgBytes);
1191 				Stream_Read_UINT32(pdu->s, Pointer);
1192 
1193 				if (Pointer)
1194 				{
1195 					if (Stream_GetRemainingLength(pdu->s) < 12)
1196 						goto fail;
1197 
1198 					Stream_Seek_UINT32(pdu->s); /* MaxCount (4 bytes) */
1199 					Stream_Seek_UINT32(pdu->s); /* Offset (4 bytes) */
1200 					Stream_Seek_UINT32(pdu->s); /* Length (4 bytes) */
1201 				}
1202 
1203 				if (packetStringMessage.msgBytes > TSG_MESSAGING_MAX_MESSAGE_LENGTH)
1204 				{
1205 					WLog_ERR(TAG, "Out of Spec Message Length %" PRIu32 "",
1206 					         packetStringMessage.msgBytes);
1207 					goto fail;
1208 				}
1209 
1210 				packetStringMessage.msgBuffer = (WCHAR*)Stream_Pointer(pdu->s);
1211 				if (Stream_GetRemainingLength(pdu->s) < packetStringMessage.msgBytes)
1212 				{
1213 					WLog_ERR(TAG, "Unable to read message (%" PRIu32 " remaining %" PRId32 ")",
1214 					         packetStringMessage.msgBytes, Stream_GetRemainingLength(pdu->s));
1215 					goto fail;
1216 				}
1217 
1218 				if (context->instance)
1219 				{
1220 					rc = IFCALLRESULT(
1221 					    TRUE, context->instance->PresentGatewayMessage, context->instance,
1222 					    TSG_ASYNC_MESSAGE_CONSENT_MESSAGE ? GATEWAY_MESSAGE_CONSENT
1223 					                                      : TSG_ASYNC_MESSAGE_SERVICE_MESSAGE,
1224 					    packetStringMessage.isDisplayMandatory != 0,
1225 					    packetStringMessage.isConsentMandatory != 0, packetStringMessage.msgBytes,
1226 					    packetStringMessage.msgBuffer);
1227 					if (!rc)
1228 						goto fail;
1229 				}
1230 
1231 				Stream_Seek(pdu->s, packetStringMessage.msgBytes);
1232 				break;
1233 
1234 			case TSG_ASYNC_MESSAGE_REAUTH:
1235 			{
1236 				if (!tsg_stream_align(pdu->s, 8))
1237 					goto fail;
1238 
1239 				if (Stream_GetRemainingLength(pdu->s) < 8)
1240 					goto fail;
1241 
1242 				Stream_Seek_UINT64(pdu->s); /* TunnelContext (8 bytes) */
1243 			}
1244 			break;
1245 
1246 			default:
1247 				WLog_ERR(TAG, "Unexpected Message Type: 0x%" PRIX32 "", MessageSwitchValue);
1248 				goto fail;
1249 		}
1250 
1251 		if (!tsg_stream_align(pdu->s, 4))
1252 			goto fail;
1253 
1254 		/* TunnelContext (20 bytes) */
1255 		if (Stream_GetRemainingLength(pdu->s) < 24)
1256 			goto fail;
1257 
1258 		Stream_Read_UINT32(pdu->s, tunnelContext->ContextType); /* ContextType (4 bytes) */
1259 		Stream_Read(pdu->s, tunnelContext->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1260 		Stream_Read_UINT32(pdu->s, *tunnelId);                  /* TunnelId (4 bytes) */
1261 		                                                        /* ReturnValue (4 bytes) */
1262 	}
1263 	else if ((packet->packetId == TSG_PACKET_TYPE_QUARENC_RESPONSE) &&
1264 	         (SwitchValue == TSG_PACKET_TYPE_QUARENC_RESPONSE))
1265 	{
1266 		packetQuarEncResponse =
1267 		    (PTSG_PACKET_QUARENC_RESPONSE)calloc(1, sizeof(TSG_PACKET_QUARENC_RESPONSE));
1268 
1269 		if (!packetQuarEncResponse)
1270 			goto fail;
1271 
1272 		packet->tsgPacket.packetQuarEncResponse = packetQuarEncResponse;
1273 
1274 		if (Stream_GetRemainingLength(pdu->s) < 32)
1275 			goto fail;
1276 
1277 		Stream_Seek_UINT32(pdu->s); /* PacketQuarResponsePtr (4 bytes) */
1278 		Stream_Read_UINT32(pdu->s, packetQuarEncResponse->flags); /* Flags (4 bytes) */
1279 		Stream_Read_UINT32(pdu->s,
1280 		                   packetQuarEncResponse->certChainLen); /* CertChainLength (4 bytes) */
1281 		Stream_Seek_UINT32(pdu->s);                              /* CertChainDataPtr (4 bytes) */
1282 		Stream_Read(pdu->s, &packetQuarEncResponse->nonce, 16);  /* Nonce (16 bytes) */
1283 
1284 		if (packetQuarEncResponse->certChainLen > 0)
1285 		{
1286 			if (Stream_GetRemainingLength(pdu->s) < 16)
1287 				goto fail;
1288 
1289 			Stream_Read_UINT32(pdu->s, Pointer); /* Ptr (4 bytes): 0x0002000C */
1290 			Stream_Seek_UINT32(pdu->s);          /* MaxCount (4 bytes) */
1291 			Stream_Seek_UINT32(pdu->s);          /* Offset (4 bytes) */
1292 			Stream_Read_UINT32(pdu->s, count);   /* ActualCount (4 bytes) */
1293 
1294 			/*
1295 			 * CertChainData is a wide character string, and the count is
1296 			 * given in characters excluding the null terminator, therefore:
1297 			 * size = (count * 2)
1298 			 */
1299 			if (!Stream_SafeSeek(pdu->s, count * 2)) /* CertChainData */
1300 				goto fail;
1301 
1302 			/* 4-byte alignment */
1303 			if (!tsg_stream_align(pdu->s, 4))
1304 				goto fail;
1305 		}
1306 		else
1307 		{
1308 			if (Stream_GetRemainingLength(pdu->s) < 4)
1309 				goto fail;
1310 
1311 			Stream_Read_UINT32(pdu->s, Pointer); /* Ptr (4 bytes): 0x00020008 */
1312 		}
1313 
1314 		versionCaps = (PTSG_PACKET_VERSIONCAPS)calloc(1, sizeof(TSG_PACKET_VERSIONCAPS));
1315 
1316 		if (!versionCaps)
1317 			goto fail;
1318 
1319 		packetQuarEncResponse->versionCaps = versionCaps;
1320 
1321 		if (Stream_GetRemainingLength(pdu->s) < 18)
1322 			goto fail;
1323 
1324 		Stream_Read_UINT16(pdu->s, versionCaps->tsgHeader.ComponentId); /* ComponentId (2 bytes) */
1325 		Stream_Read_UINT16(pdu->s, versionCaps->tsgHeader.PacketId);    /* PacketId (2 bytes) */
1326 
1327 		if (versionCaps->tsgHeader.ComponentId != TS_GATEWAY_TRANSPORT)
1328 		{
1329 			WLog_ERR(TAG, "Unexpected ComponentId: 0x%04" PRIX16 ", Expected TS_GATEWAY_TRANSPORT",
1330 			         versionCaps->tsgHeader.ComponentId);
1331 			goto fail;
1332 		}
1333 
1334 		Stream_Read_UINT32(pdu->s, Pointer);                      /* TsgCapsPtr (4 bytes) */
1335 		Stream_Read_UINT32(pdu->s, versionCaps->numCapabilities); /* NumCapabilities (4 bytes) */
1336 		Stream_Read_UINT16(pdu->s, versionCaps->majorVersion);    /* MajorVersion (2 bytes) */
1337 		Stream_Read_UINT16(pdu->s, versionCaps->minorVersion);    /* MinorVersion (2 bytes) */
1338 		Stream_Read_UINT16(
1339 		    pdu->s, versionCaps->quarantineCapabilities); /* QuarantineCapabilities (2 bytes) */
1340 
1341 		/* 4-byte alignment */
1342 		if (!tsg_stream_align(pdu->s, 4))
1343 			goto fail;
1344 
1345 		if (Stream_GetRemainingLength(pdu->s) < 36)
1346 			goto fail;
1347 
1348 		/* Not sure exactly what this is */
1349 		Stream_Seek_UINT32(pdu->s); /* 0x00000001 (4 bytes) */
1350 		Stream_Seek_UINT32(pdu->s); /* 0x00000001 (4 bytes) */
1351 		Stream_Seek_UINT32(pdu->s); /* 0x00000001 (4 bytes) */
1352 		Stream_Seek_UINT32(pdu->s); /* 0x00000002 (4 bytes) */
1353 		/* TunnelContext (20 bytes) */
1354 		Stream_Read_UINT32(pdu->s, tunnelContext->ContextType); /* ContextType (4 bytes) */
1355 		Stream_Read(pdu->s, tunnelContext->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1356 	}
1357 	else
1358 	{
1359 		WLog_ERR(TAG,
1360 		         "Unexpected PacketId: 0x%08" PRIX32 ", Expected TSG_PACKET_TYPE_CAPS_RESPONSE "
1361 		         "or TSG_PACKET_TYPE_QUARENC_RESPONSE",
1362 		         packet->packetId);
1363 		goto fail;
1364 	}
1365 
1366 	rc = TRUE;
1367 fail:
1368 	free(packetQuarEncResponse);
1369 	free(packetCapsResponse);
1370 	free(versionCaps);
1371 	free(tsgCaps);
1372 	free(packet);
1373 	return rc;
1374 }
1375 
1376 /**
1377  * OpNum = 2
1378  *
1379  * HRESULT TsProxyAuthorizeTunnel(
1380  * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext,
1381  * [in, ref] PTSG_PACKET tsgPacket,
1382  * [out, ref] PTSG_PACKET* tsgPacketResponse
1383  * );
1384  *
1385  */
1386 
TsProxyAuthorizeTunnelWriteRequest(rdpTsg * tsg,CONTEXT_HANDLE * tunnelContext)1387 static BOOL TsProxyAuthorizeTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext)
1388 {
1389 	size_t pad;
1390 	wStream* s;
1391 	size_t count;
1392 	size_t offset;
1393 	rdpRpc* rpc;
1394 
1395 	if (!tsg || !tsg->rpc || !tunnelContext || !tsg->MachineName)
1396 		return FALSE;
1397 
1398 	count = _wcslen(tsg->MachineName) + 1;
1399 	if (count > UINT32_MAX)
1400 		return FALSE;
1401 
1402 	rpc = tsg->rpc;
1403 	WLog_DBG(TAG, "TsProxyAuthorizeTunnelWriteRequest");
1404 	s = Stream_New(NULL, 1024 + count * 2);
1405 
1406 	if (!s)
1407 		return FALSE;
1408 
1409 	/* TunnelContext (20 bytes) */
1410 	Stream_Write_UINT32(s, tunnelContext->ContextType); /* ContextType (4 bytes) */
1411 	Stream_Write(s, &tunnelContext->ContextUuid, 16);   /* ContextUuid (16 bytes) */
1412 	/* 4-byte alignment */
1413 	Stream_Write_UINT32(s, TSG_PACKET_TYPE_QUARREQUEST); /* PacketId (4 bytes) */
1414 	Stream_Write_UINT32(s, TSG_PACKET_TYPE_QUARREQUEST); /* SwitchValue (4 bytes) */
1415 	Stream_Write_UINT32(s, 0x00020000);                  /* PacketQuarRequestPtr (4 bytes) */
1416 	Stream_Write_UINT32(s, 0x00000000);                  /* Flags (4 bytes) */
1417 	Stream_Write_UINT32(s, 0x00020004);                  /* MachineNamePtr (4 bytes) */
1418 	Stream_Write_UINT32(s, (UINT32)count);               /* NameLength (4 bytes) */
1419 	Stream_Write_UINT32(s, 0x00020008);                  /* DataPtr (4 bytes) */
1420 	Stream_Write_UINT32(s, 0);                           /* DataLength (4 bytes) */
1421 	/* MachineName */
1422 	Stream_Write_UINT32(s, (UINT32)count);                 /* MaxCount (4 bytes) */
1423 	Stream_Write_UINT32(s, 0);                             /* Offset (4 bytes) */
1424 	Stream_Write_UINT32(s, (UINT32)count);                 /* ActualCount (4 bytes) */
1425 	Stream_Write_UTF16_String(s, tsg->MachineName, count); /* Array */
1426 	/* 4-byte alignment */
1427 	offset = Stream_GetPosition(s);
1428 	pad = rpc_offset_align(&offset, 4);
1429 	Stream_Zero(s, pad);
1430 	Stream_Write_UINT32(s, 0x00000000); /* MaxCount (4 bytes) */
1431 	Stream_SealLength(s);
1432 	return rpc_client_write_call(rpc, s, TsProxyAuthorizeTunnelOpnum);
1433 }
1434 
TsProxyAuthorizeTunnelReadResponse(RPC_PDU * pdu)1435 static BOOL TsProxyAuthorizeTunnelReadResponse(RPC_PDU* pdu)
1436 {
1437 	BOOL rc = FALSE;
1438 	UINT32 Pointer;
1439 	UINT32 SizeValue;
1440 	UINT32 SwitchValue;
1441 	UINT32 idleTimeout;
1442 	PTSG_PACKET packet = NULL;
1443 	PTSG_PACKET_RESPONSE packetResponse = NULL;
1444 
1445 	if (!pdu)
1446 		return FALSE;
1447 
1448 	packet = (PTSG_PACKET)calloc(1, sizeof(TSG_PACKET));
1449 
1450 	if (!packet)
1451 		return FALSE;
1452 
1453 	if (Stream_GetRemainingLength(pdu->s) < 68)
1454 		goto fail;
1455 
1456 	Stream_Seek_UINT32(pdu->s);                   /* PacketPtr (4 bytes) */
1457 	Stream_Read_UINT32(pdu->s, packet->packetId); /* PacketId (4 bytes) */
1458 	Stream_Read_UINT32(pdu->s, SwitchValue);      /* SwitchValue (4 bytes) */
1459 
1460 	WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet->packetId));
1461 
1462 	if (packet->packetId == E_PROXY_NAP_ACCESSDENIED)
1463 	{
1464 		WLog_ERR(TAG, "status: E_PROXY_NAP_ACCESSDENIED (0x%08X)", E_PROXY_NAP_ACCESSDENIED);
1465 		WLog_ERR(TAG, "Ensure that the Gateway Connection Authorization Policy is correct");
1466 		goto fail;
1467 	}
1468 
1469 	if ((packet->packetId != TSG_PACKET_TYPE_RESPONSE) || (SwitchValue != TSG_PACKET_TYPE_RESPONSE))
1470 	{
1471 		WLog_ERR(TAG, "Unexpected PacketId: 0x%08" PRIX32 ", Expected TSG_PACKET_TYPE_RESPONSE",
1472 		         packet->packetId);
1473 		goto fail;
1474 	}
1475 
1476 	packetResponse = (PTSG_PACKET_RESPONSE)calloc(1, sizeof(TSG_PACKET_RESPONSE));
1477 
1478 	if (!packetResponse)
1479 		goto fail;
1480 
1481 	packet->tsgPacket.packetResponse = packetResponse;
1482 	Stream_Read_UINT32(pdu->s, Pointer);               /* PacketResponsePtr (4 bytes) */
1483 	Stream_Read_UINT32(pdu->s, packetResponse->flags); /* Flags (4 bytes) */
1484 
1485 	if (packetResponse->flags != TSG_PACKET_TYPE_QUARREQUEST)
1486 	{
1487 		WLog_ERR(TAG,
1488 		         "Unexpected Packet Response Flags: 0x%08" PRIX32
1489 		         ", Expected TSG_PACKET_TYPE_QUARREQUEST",
1490 		         packetResponse->flags);
1491 		goto fail;
1492 	}
1493 
1494 	Stream_Seek_UINT32(pdu->s);                                  /* Reserved (4 bytes) */
1495 	Stream_Read_UINT32(pdu->s, Pointer);                         /* ResponseDataPtr (4 bytes) */
1496 	Stream_Read_UINT32(pdu->s, packetResponse->responseDataLen); /* ResponseDataLength (4 bytes) */
1497 	Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
1498 	                              .enableAllRedirections); /* EnableAllRedirections (4 bytes) */
1499 	Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
1500 	                              .disableAllRedirections); /* DisableAllRedirections (4 bytes) */
1501 	Stream_Read_INT32(pdu->s,
1502 	                  packetResponse->redirectionFlags
1503 	                      .driveRedirectionDisabled); /* DriveRedirectionDisabled (4 bytes) */
1504 	Stream_Read_INT32(pdu->s,
1505 	                  packetResponse->redirectionFlags
1506 	                      .printerRedirectionDisabled); /* PrinterRedirectionDisabled (4 bytes) */
1507 	Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
1508 	                              .portRedirectionDisabled); /* PortRedirectionDisabled (4 bytes) */
1509 	Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags.reserved); /* Reserved (4 bytes) */
1510 	Stream_Read_INT32(
1511 	    pdu->s, packetResponse->redirectionFlags
1512 	                .clipboardRedirectionDisabled); /* ClipboardRedirectionDisabled (4 bytes) */
1513 	Stream_Read_INT32(pdu->s, packetResponse->redirectionFlags
1514 	                              .pnpRedirectionDisabled);  /* PnpRedirectionDisabled (4 bytes) */
1515 	Stream_Read_UINT32(pdu->s, SizeValue);                   /* (4 bytes) */
1516 
1517 	if (SizeValue != packetResponse->responseDataLen)
1518 	{
1519 		WLog_ERR(TAG, "Unexpected size value: %" PRIu32 ", expected: %" PRIu32 "", SizeValue,
1520 		         packetResponse->responseDataLen);
1521 		goto fail;
1522 	}
1523 
1524 	if (Stream_GetRemainingLength(pdu->s) < SizeValue)
1525 		goto fail;
1526 
1527 	if (SizeValue == 4)
1528 		Stream_Read_UINT32(pdu->s, idleTimeout);
1529 	else
1530 		Stream_Seek(pdu->s, SizeValue); /* ResponseData */
1531 
1532 	rc = TRUE;
1533 fail:
1534 	free(packetResponse);
1535 	free(packet);
1536 	return rc;
1537 }
1538 
1539 /**
1540  * OpNum = 3
1541  *
1542  * HRESULT TsProxyMakeTunnelCall(
1543  * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext,
1544  * [in] unsigned long procId,
1545  * [in, ref] PTSG_PACKET tsgPacket,
1546  * [out, ref] PTSG_PACKET* tsgPacketResponse
1547  * );
1548  */
1549 
TsProxyMakeTunnelCallWriteRequest(rdpTsg * tsg,CONTEXT_HANDLE * tunnelContext,UINT32 procId)1550 static BOOL TsProxyMakeTunnelCallWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext,
1551                                               UINT32 procId)
1552 {
1553 	wStream* s;
1554 	rdpRpc* rpc;
1555 
1556 	if (!tsg || !tsg->rpc || !tunnelContext)
1557 		return FALSE;
1558 
1559 	rpc = tsg->rpc;
1560 	WLog_DBG(TAG, "TsProxyMakeTunnelCallWriteRequest");
1561 	s = Stream_New(NULL, 40);
1562 
1563 	if (!s)
1564 		return FALSE;
1565 
1566 	/* TunnelContext (20 bytes) */
1567 	Stream_Write_UINT32(s, tunnelContext->ContextType); /* ContextType (4 bytes) */
1568 	Stream_Write(s, tunnelContext->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1569 	Stream_Write_UINT32(s, procId);                     /* ProcId (4 bytes) */
1570 	/* 4-byte alignment */
1571 	Stream_Write_UINT32(s, TSG_PACKET_TYPE_MSGREQUEST_PACKET); /* PacketId (4 bytes) */
1572 	Stream_Write_UINT32(s, TSG_PACKET_TYPE_MSGREQUEST_PACKET); /* SwitchValue (4 bytes) */
1573 	Stream_Write_UINT32(s, 0x00020000);                        /* PacketMsgRequestPtr (4 bytes) */
1574 	Stream_Write_UINT32(s, 0x00000001);                        /* MaxMessagesPerBatch (4 bytes) */
1575 	return rpc_client_write_call(rpc, s, TsProxyMakeTunnelCallOpnum);
1576 }
1577 
TsProxyReadPacketSTringMessage(rdpTsg * tsg,wStream * s,TSG_PACKET_STRING_MESSAGE * msg)1578 static BOOL TsProxyReadPacketSTringMessage(rdpTsg* tsg, wStream* s, TSG_PACKET_STRING_MESSAGE* msg)
1579 {
1580 	UINT32 Pointer, ActualCount, MaxCount;
1581 	if (!tsg || !s || !msg)
1582 		return FALSE;
1583 
1584 	if (Stream_GetRemainingLength(s) < 32)
1585 		return FALSE;
1586 
1587 	Stream_Read_UINT32(s, Pointer);                /* ConsentMessagePtr (4 bytes) */
1588 	Stream_Read_INT32(s, msg->isDisplayMandatory); /* IsDisplayMandatory (4 bytes) */
1589 	Stream_Read_INT32(s, msg->isConsentMandatory); /* IsConsentMandatory (4 bytes) */
1590 	Stream_Read_UINT32(s, msg->msgBytes);          /* MsgBytes (4 bytes) */
1591 	Stream_Read_UINT32(s, Pointer);                /* MsgPtr (4 bytes) */
1592 	Stream_Read_UINT32(s, MaxCount);               /* MaxCount (4 bytes) */
1593 	Stream_Seek_UINT32(s);                         /* Offset (4 bytes) */
1594 	Stream_Read_UINT32(s, ActualCount);            /* ActualCount (4 bytes) */
1595 
1596 	if (msg->msgBytes < ActualCount * 2)
1597 		return FALSE;
1598 
1599 	if (Stream_GetRemainingLength(s) < msg->msgBytes)
1600 		return FALSE;
1601 
1602 	msg->msgBuffer = (WCHAR*)Stream_Pointer(s);
1603 	Stream_Seek(s, msg->msgBytes);
1604 
1605 	return TRUE;
1606 }
1607 
TsProxyMakeTunnelCallReadResponse(rdpTsg * tsg,RPC_PDU * pdu)1608 static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
1609 {
1610 	BOOL rc = FALSE;
1611 	UINT32 Pointer;
1612 	UINT32 SwitchValue;
1613 	TSG_PACKET packet;
1614 	rdpContext* context;
1615 	char* messageText = NULL;
1616 	TSG_PACKET_MSG_RESPONSE packetMsgResponse = { 0 };
1617 	TSG_PACKET_STRING_MESSAGE packetStringMessage = { 0 };
1618 	TSG_PACKET_REAUTH_MESSAGE packetReauthMessage = { 0 };
1619 
1620 	assert(tsg);
1621 	assert(tsg->rpc);
1622 
1623 	context = tsg->rpc->context;
1624 	assert(context);
1625 
1626 	/* This is an asynchronous response */
1627 
1628 	if (!pdu)
1629 		return FALSE;
1630 
1631 	if (Stream_GetRemainingLength(pdu->s) < 28)
1632 		goto fail;
1633 
1634 	Stream_Seek_UINT32(pdu->s);                  /* PacketPtr (4 bytes) */
1635 	Stream_Read_UINT32(pdu->s, packet.packetId); /* PacketId (4 bytes) */
1636 	Stream_Read_UINT32(pdu->s, SwitchValue);     /* SwitchValue (4 bytes) */
1637 
1638 	WLog_DBG(TAG, "%s: %s", __FUNCTION__, tsg_packet_id_to_string(packet.packetId));
1639 
1640 	if ((packet.packetId != TSG_PACKET_TYPE_MESSAGE_PACKET) ||
1641 	    (SwitchValue != TSG_PACKET_TYPE_MESSAGE_PACKET))
1642 	{
1643 		WLog_ERR(TAG,
1644 		         "Unexpected PacketId: 0x%08" PRIX32 ", Expected TSG_PACKET_TYPE_MESSAGE_PACKET",
1645 		         packet.packetId);
1646 		goto fail;
1647 	}
1648 
1649 	Stream_Read_UINT32(pdu->s, Pointer);                       /* PacketMsgResponsePtr (4 bytes) */
1650 	Stream_Read_UINT32(pdu->s, packetMsgResponse.msgID);       /* MsgId (4 bytes) */
1651 	Stream_Read_UINT32(pdu->s, packetMsgResponse.msgType);     /* MsgType (4 bytes) */
1652 	Stream_Read_INT32(pdu->s, packetMsgResponse.isMsgPresent); /* IsMsgPresent (4 bytes) */
1653 
1654 	/* 2.2.9.2.1.9 TSG_PACKET_MSG_RESPONSE: Ignore empty message body. */
1655 	if (!packetMsgResponse.isMsgPresent)
1656 	{
1657 		rc = TRUE;
1658 		goto fail;
1659 	}
1660 
1661 	Stream_Read_UINT32(pdu->s, SwitchValue); /* SwitchValue (4 bytes) */
1662 
1663 	switch (SwitchValue)
1664 	{
1665 		case TSG_ASYNC_MESSAGE_CONSENT_MESSAGE:
1666 			if (!TsProxyReadPacketSTringMessage(tsg, pdu->s, &packetStringMessage))
1667 				goto fail;
1668 
1669 			ConvertFromUnicode(CP_UTF8, 0, packetStringMessage.msgBuffer,
1670 			                   packetStringMessage.msgBytes / 2, &messageText, 0, NULL, NULL);
1671 
1672 			WLog_INFO(TAG, "Consent Message: %s", messageText);
1673 			free(messageText);
1674 
1675 			if (context->instance)
1676 			{
1677 				rc = IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance,
1678 				                  GATEWAY_MESSAGE_CONSENT,
1679 				                  packetStringMessage.isDisplayMandatory != 0,
1680 				                  packetStringMessage.isConsentMandatory != 0,
1681 				                  packetStringMessage.msgBytes, packetStringMessage.msgBuffer);
1682 			}
1683 
1684 			break;
1685 
1686 		case TSG_ASYNC_MESSAGE_SERVICE_MESSAGE:
1687 			if (!TsProxyReadPacketSTringMessage(tsg, pdu->s, &packetStringMessage))
1688 				goto fail;
1689 
1690 			ConvertFromUnicode(CP_UTF8, 0, packetStringMessage.msgBuffer,
1691 			                   packetStringMessage.msgBytes / 2, &messageText, 0, NULL, NULL);
1692 
1693 			WLog_INFO(TAG, "Service Message: %s", messageText);
1694 			free(messageText);
1695 
1696 			if (context->instance)
1697 			{
1698 				rc = IFCALLRESULT(TRUE, context->instance->PresentGatewayMessage, context->instance,
1699 				                  GATEWAY_MESSAGE_SERVICE,
1700 				                  packetStringMessage.isDisplayMandatory != 0,
1701 				                  packetStringMessage.isConsentMandatory != 0,
1702 				                  packetStringMessage.msgBytes, packetStringMessage.msgBuffer);
1703 			}
1704 			break;
1705 
1706 		case TSG_ASYNC_MESSAGE_REAUTH:
1707 			if (Stream_GetRemainingLength(pdu->s) < 20)
1708 				goto fail;
1709 
1710 			Stream_Read_UINT32(pdu->s, Pointer); /* ReauthMessagePtr (4 bytes) */
1711 			Stream_Seek_UINT32(pdu->s);          /* alignment pad (4 bytes) */
1712 			Stream_Read_UINT64(pdu->s,
1713 			                   packetReauthMessage.tunnelContext); /* TunnelContext (8 bytes) */
1714 			Stream_Seek_UINT32(pdu->s);                            /* ReturnValue (4 bytes) */
1715 			tsg->ReauthTunnelContext = packetReauthMessage.tunnelContext;
1716 			break;
1717 
1718 		default:
1719 			WLog_ERR(TAG, "unexpected message type: %" PRIu32 "", SwitchValue);
1720 			goto fail;
1721 	}
1722 
1723 	rc = TRUE;
1724 fail:
1725 	return rc;
1726 }
1727 
1728 /**
1729  * OpNum = 4
1730  *
1731  * HRESULT TsProxyCreateChannel(
1732  * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext,
1733  * [in, ref] PTSENDPOINTINFO tsEndPointInfo,
1734  * [out] PCHANNEL_CONTEXT_HANDLE_SERIALIZE* channelContext,
1735  * [out] unsigned long* channelId
1736  * );
1737  */
1738 
TsProxyCreateChannelWriteRequest(rdpTsg * tsg,CONTEXT_HANDLE * tunnelContext)1739 static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext)
1740 {
1741 	size_t count;
1742 	wStream* s;
1743 	rdpRpc* rpc;
1744 	WLog_DBG(TAG, "TsProxyCreateChannelWriteRequest");
1745 
1746 	if (!tsg || !tsg->rpc || !tunnelContext || !tsg->Hostname)
1747 		return FALSE;
1748 
1749 	rpc = tsg->rpc;
1750 	count = _wcslen(tsg->Hostname) + 1;
1751 	if (count > UINT32_MAX)
1752 		return FALSE;
1753 	s = Stream_New(NULL, 60 + count * 2);
1754 
1755 	if (!s)
1756 		return FALSE;
1757 
1758 	/* TunnelContext (20 bytes) */
1759 	Stream_Write_UINT32(s, tunnelContext->ContextType); /* ContextType (4 bytes) */
1760 	Stream_Write(s, tunnelContext->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1761 	/* TSENDPOINTINFO */
1762 	Stream_Write_UINT32(s, 0x00020000); /* ResourceNamePtr (4 bytes) */
1763 	Stream_Write_UINT32(s, 0x00000001); /* NumResourceNames (4 bytes) */
1764 	Stream_Write_UINT32(s, 0x00000000); /* AlternateResourceNamesPtr (4 bytes) */
1765 	Stream_Write_UINT16(s, 0x0000);     /* NumAlternateResourceNames (2 bytes) */
1766 	Stream_Write_UINT16(s, 0x0000);     /* Pad (2 bytes) */
1767 	/* Port (4 bytes) */
1768 	Stream_Write_UINT16(s, 0x0003);                     /* ProtocolId (RDP = 3) (2 bytes) */
1769 	Stream_Write_UINT16(s, tsg->Port);                  /* PortNumber (0xD3D = 3389) (2 bytes) */
1770 	Stream_Write_UINT32(s, 0x00000001);                 /* NumResourceNames (4 bytes) */
1771 	Stream_Write_UINT32(s, 0x00020004);                 /* ResourceNamePtr (4 bytes) */
1772 	Stream_Write_UINT32(s, (UINT32)count);              /* MaxCount (4 bytes) */
1773 	Stream_Write_UINT32(s, 0);                          /* Offset (4 bytes) */
1774 	Stream_Write_UINT32(s, (UINT32)count);              /* ActualCount (4 bytes) */
1775 	Stream_Write_UTF16_String(s, tsg->Hostname, count); /* Array */
1776 	return rpc_client_write_call(rpc, s, TsProxyCreateChannelOpnum);
1777 }
1778 
TsProxyCreateChannelReadResponse(RPC_PDU * pdu,CONTEXT_HANDLE * channelContext,UINT32 * channelId)1779 static BOOL TsProxyCreateChannelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* channelContext,
1780                                              UINT32* channelId)
1781 {
1782 	BOOL rc = FALSE;
1783 	WLog_DBG(TAG, "TsProxyCreateChannelReadResponse");
1784 
1785 	if (!pdu)
1786 		return FALSE;
1787 
1788 	if (Stream_GetRemainingLength(pdu->s) < 28)
1789 		goto fail;
1790 
1791 	/* ChannelContext (20 bytes) */
1792 	Stream_Read_UINT32(pdu->s, channelContext->ContextType); /* ContextType (4 bytes) */
1793 	Stream_Read(pdu->s, channelContext->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1794 	Stream_Read_UINT32(pdu->s, *channelId);                  /* ChannelId (4 bytes) */
1795 	Stream_Seek_UINT32(pdu->s);                              /* ReturnValue (4 bytes) */
1796 	rc = TRUE;
1797 fail:
1798 	return rc;
1799 }
1800 
1801 /**
1802  * HRESULT TsProxyCloseChannel(
1803  * [in, out] PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE* context
1804  * );
1805  */
1806 
TsProxyCloseChannelWriteRequest(rdpTsg * tsg,CONTEXT_HANDLE * context)1807 static BOOL TsProxyCloseChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context)
1808 {
1809 	wStream* s;
1810 	rdpRpc* rpc;
1811 	WLog_DBG(TAG, "TsProxyCloseChannelWriteRequest");
1812 
1813 	if (!tsg || !tsg->rpc || !context)
1814 		return FALSE;
1815 
1816 	rpc = tsg->rpc;
1817 	s = Stream_New(NULL, 20);
1818 
1819 	if (!s)
1820 		return FALSE;
1821 
1822 	/* ChannelContext (20 bytes) */
1823 	Stream_Write_UINT32(s, context->ContextType); /* ContextType (4 bytes) */
1824 	Stream_Write(s, context->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1825 	return rpc_client_write_call(rpc, s, TsProxyCloseChannelOpnum);
1826 }
1827 
TsProxyCloseChannelReadResponse(RPC_PDU * pdu,CONTEXT_HANDLE * context)1828 static BOOL TsProxyCloseChannelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* context)
1829 {
1830 	BOOL rc = FALSE;
1831 	WLog_DBG(TAG, "TsProxyCloseChannelReadResponse");
1832 
1833 	if (!pdu)
1834 		return FALSE;
1835 
1836 	if (Stream_GetRemainingLength(pdu->s) < 24)
1837 		goto fail;
1838 
1839 	/* ChannelContext (20 bytes) */
1840 	Stream_Read_UINT32(pdu->s, context->ContextType); /* ContextType (4 bytes) */
1841 	Stream_Read(pdu->s, context->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1842 	Stream_Seek_UINT32(pdu->s);                       /* ReturnValue (4 bytes) */
1843 	rc = TRUE;
1844 fail:
1845 	return rc;
1846 }
1847 
1848 /**
1849  * HRESULT TsProxyCloseTunnel(
1850  * [in, out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* context
1851  * );
1852  */
1853 
TsProxyCloseTunnelWriteRequest(rdpTsg * tsg,CONTEXT_HANDLE * context)1854 static BOOL TsProxyCloseTunnelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context)
1855 {
1856 	wStream* s;
1857 	rdpRpc* rpc;
1858 	WLog_DBG(TAG, "TsProxyCloseTunnelWriteRequest");
1859 
1860 	if (!tsg || !tsg->rpc || !context)
1861 		return FALSE;
1862 
1863 	rpc = tsg->rpc;
1864 	s = Stream_New(NULL, 20);
1865 
1866 	if (!s)
1867 		return FALSE;
1868 
1869 	/* TunnelContext (20 bytes) */
1870 	Stream_Write_UINT32(s, context->ContextType); /* ContextType (4 bytes) */
1871 	Stream_Write(s, context->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1872 	return rpc_client_write_call(rpc, s, TsProxyCloseTunnelOpnum);
1873 }
1874 
TsProxyCloseTunnelReadResponse(RPC_PDU * pdu,CONTEXT_HANDLE * context)1875 static BOOL TsProxyCloseTunnelReadResponse(RPC_PDU* pdu, CONTEXT_HANDLE* context)
1876 {
1877 	BOOL rc = FALSE;
1878 	WLog_DBG(TAG, "TsProxyCloseTunnelReadResponse");
1879 
1880 	if (!pdu || !context)
1881 		return FALSE;
1882 
1883 	if (Stream_GetRemainingLength(pdu->s) < 24)
1884 		goto fail;
1885 
1886 	/* TunnelContext (20 bytes) */
1887 	Stream_Read_UINT32(pdu->s, context->ContextType); /* ContextType (4 bytes) */
1888 	Stream_Read(pdu->s, context->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1889 	Stream_Seek_UINT32(pdu->s);                       /* ReturnValue (4 bytes) */
1890 	rc = TRUE;
1891 fail:
1892 	return rc;
1893 }
1894 
1895 /**
1896  * OpNum = 8
1897  *
1898  * DWORD TsProxySetupReceivePipe(
1899  * [in, max_is(32767)] byte pRpcMessage[]
1900  * );
1901  */
1902 
TsProxySetupReceivePipeWriteRequest(rdpTsg * tsg,CONTEXT_HANDLE * channelContext)1903 static BOOL TsProxySetupReceivePipeWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* channelContext)
1904 {
1905 	wStream* s;
1906 	rdpRpc* rpc;
1907 	WLog_DBG(TAG, "TsProxySetupReceivePipeWriteRequest");
1908 
1909 	if (!tsg || !tsg->rpc || !channelContext)
1910 		return FALSE;
1911 
1912 	rpc = tsg->rpc;
1913 	s = Stream_New(NULL, 20);
1914 
1915 	if (!s)
1916 		return FALSE;
1917 
1918 	/* ChannelContext (20 bytes) */
1919 	Stream_Write_UINT32(s, channelContext->ContextType); /* ContextType (4 bytes) */
1920 	Stream_Write(s, channelContext->ContextUuid, 16);    /* ContextUuid (16 bytes) */
1921 	return rpc_client_write_call(rpc, s, TsProxySetupReceivePipeOpnum);
1922 }
1923 
tsg_transition_to_state(rdpTsg * tsg,TSG_STATE state)1924 static BOOL tsg_transition_to_state(rdpTsg* tsg, TSG_STATE state)
1925 {
1926 	const char* oldState = tsg_state_to_string(tsg->state);
1927 	const char* newState = tsg_state_to_string(state);
1928 
1929 	WLog_DBG(TAG, "%s -> %s", oldState, newState);
1930 	return tsg_set_state(tsg, state);
1931 }
1932 
tsg_proxy_begin(rdpTsg * tsg)1933 BOOL tsg_proxy_begin(rdpTsg* tsg)
1934 {
1935 	TSG_PACKET tsgPacket = { 0 };
1936 	PTSG_CAPABILITY_NAP tsgCapNap;
1937 	PTSG_PACKET_VERSIONCAPS packetVersionCaps;
1938 
1939 	if (!tsg)
1940 		return FALSE;
1941 
1942 	packetVersionCaps = &tsg->packetVersionCaps;
1943 	packetVersionCaps->tsgCaps = &tsg->tsgCaps;
1944 	tsgCapNap = &tsg->tsgCaps.tsgPacket.tsgCapNap;
1945 	tsgPacket.packetId = TSG_PACKET_TYPE_VERSIONCAPS;
1946 	tsgPacket.tsgPacket.packetVersionCaps = packetVersionCaps;
1947 	packetVersionCaps->tsgHeader.ComponentId = TS_GATEWAY_TRANSPORT;
1948 	packetVersionCaps->tsgHeader.PacketId = TSG_PACKET_TYPE_VERSIONCAPS;
1949 	packetVersionCaps->numCapabilities = 1;
1950 	packetVersionCaps->majorVersion = 1;
1951 	packetVersionCaps->minorVersion = 1;
1952 	packetVersionCaps->quarantineCapabilities = 0;
1953 	packetVersionCaps->tsgCaps->capabilityType = TSG_CAPABILITY_TYPE_NAP;
1954 	/*
1955 	 * Using reduced capabilities appears to trigger
1956 	 * TSG_PACKET_TYPE_QUARENC_RESPONSE instead of TSG_PACKET_TYPE_CAPS_RESPONSE
1957 	 *
1958 	 * However, reduced capabilities may break connectivity with servers enforcing features, such as
1959 	 * "Only allow connections from Remote Desktop Services clients that support RD Gateway
1960 	 * messaging"
1961 	 */
1962 	tsgCapNap->capabilities = TSG_NAP_CAPABILITY_QUAR_SOH | TSG_NAP_CAPABILITY_IDLE_TIMEOUT |
1963 	                          TSG_MESSAGING_CAP_CONSENT_SIGN | TSG_MESSAGING_CAP_SERVICE_MSG |
1964 	                          TSG_MESSAGING_CAP_REAUTH;
1965 
1966 	if (!TsProxyCreateTunnelWriteRequest(tsg, &tsgPacket))
1967 	{
1968 		WLog_ERR(TAG, "TsProxyCreateTunnel failure");
1969 		tsg_transition_to_state(tsg, TSG_STATE_FINAL);
1970 		return FALSE;
1971 	}
1972 
1973 	return tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
1974 }
1975 
tsg_proxy_reauth(rdpTsg * tsg)1976 static BOOL tsg_proxy_reauth(rdpTsg* tsg)
1977 {
1978 	TSG_PACKET tsgPacket = { 0 };
1979 	PTSG_PACKET_REAUTH packetReauth;
1980 	PTSG_PACKET_VERSIONCAPS packetVersionCaps;
1981 
1982 	if (!tsg)
1983 		return FALSE;
1984 
1985 	tsg->reauthSequence = TRUE;
1986 	packetReauth = &tsg->packetReauth;
1987 	packetVersionCaps = &tsg->packetVersionCaps;
1988 
1989 	if (!packetReauth || !packetVersionCaps)
1990 		return FALSE;
1991 
1992 	tsgPacket.packetId = TSG_PACKET_TYPE_REAUTH;
1993 	tsgPacket.tsgPacket.packetReauth = &tsg->packetReauth;
1994 	packetReauth->tunnelContext = tsg->ReauthTunnelContext;
1995 	packetReauth->packetId = TSG_PACKET_TYPE_VERSIONCAPS;
1996 	packetReauth->tsgInitialPacket.packetVersionCaps = packetVersionCaps;
1997 
1998 	if (!TsProxyCreateTunnelWriteRequest(tsg, &tsgPacket))
1999 	{
2000 		WLog_ERR(TAG, "TsProxyCreateTunnel failure");
2001 		tsg_transition_to_state(tsg, TSG_STATE_FINAL);
2002 		return FALSE;
2003 	}
2004 
2005 	if (!TsProxyMakeTunnelCallWriteRequest(tsg, &tsg->TunnelContext,
2006 	                                       TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST))
2007 	{
2008 		WLog_ERR(TAG, "TsProxyMakeTunnelCall failure");
2009 		tsg_transition_to_state(tsg, TSG_STATE_FINAL);
2010 		return FALSE;
2011 	}
2012 
2013 	return tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
2014 }
2015 
tsg_recv_pdu(rdpTsg * tsg,RPC_PDU * pdu)2016 BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
2017 {
2018 	BOOL rc = FALSE;
2019 	RpcClientCall* call;
2020 	rdpRpc* rpc;
2021 
2022 	if (!tsg || !tsg->rpc || !pdu)
2023 		return FALSE;
2024 
2025 	rpc = tsg->rpc;
2026 
2027 	if (!(pdu->Flags & RPC_PDU_FLAG_STUB))
2028 	{
2029 		if (!Stream_SafeSeek(pdu->s, 24))
2030 			return FALSE;
2031 	}
2032 
2033 	switch (tsg->state)
2034 	{
2035 		case TSG_STATE_INITIAL:
2036 		{
2037 			CONTEXT_HANDLE* TunnelContext;
2038 			TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
2039 
2040 			if (!TsProxyCreateTunnelReadResponse(tsg, pdu, TunnelContext, &tsg->TunnelId))
2041 			{
2042 				WLog_ERR(TAG, "TsProxyCreateTunnelReadResponse failure");
2043 				return FALSE;
2044 			}
2045 
2046 			if (!tsg_transition_to_state(tsg, TSG_STATE_CONNECTED))
2047 				return FALSE;
2048 
2049 			if (!TsProxyAuthorizeTunnelWriteRequest(tsg, TunnelContext))
2050 			{
2051 				WLog_ERR(TAG, "TsProxyAuthorizeTunnel failure");
2052 				return FALSE;
2053 			}
2054 
2055 			rc = TRUE;
2056 		}
2057 		break;
2058 
2059 		case TSG_STATE_CONNECTED:
2060 		{
2061 			CONTEXT_HANDLE* TunnelContext;
2062 			TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
2063 
2064 			if (!TsProxyAuthorizeTunnelReadResponse(pdu))
2065 			{
2066 				WLog_ERR(TAG, "TsProxyAuthorizeTunnelReadResponse failure");
2067 				return FALSE;
2068 			}
2069 
2070 			if (!tsg_transition_to_state(tsg, TSG_STATE_AUTHORIZED))
2071 				return FALSE;
2072 
2073 			if (!tsg->reauthSequence)
2074 			{
2075 				if (!TsProxyMakeTunnelCallWriteRequest(tsg, TunnelContext,
2076 				                                       TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST))
2077 				{
2078 					WLog_ERR(TAG, "TsProxyMakeTunnelCall failure");
2079 					return FALSE;
2080 				}
2081 			}
2082 
2083 			if (!TsProxyCreateChannelWriteRequest(tsg, TunnelContext))
2084 			{
2085 				WLog_ERR(TAG, "TsProxyCreateChannel failure");
2086 				return FALSE;
2087 			}
2088 
2089 			rc = TRUE;
2090 		}
2091 		break;
2092 
2093 		case TSG_STATE_AUTHORIZED:
2094 			call = rpc_client_call_find_by_id(rpc->client, pdu->CallId);
2095 
2096 			if (!call)
2097 				return FALSE;
2098 
2099 			if (call->OpNum == TsProxyMakeTunnelCallOpnum)
2100 			{
2101 				if (!TsProxyMakeTunnelCallReadResponse(tsg, pdu))
2102 				{
2103 					WLog_ERR(TAG, "TsProxyMakeTunnelCallReadResponse failure");
2104 					return FALSE;
2105 				}
2106 
2107 				rc = TRUE;
2108 			}
2109 			else if (call->OpNum == TsProxyCreateChannelOpnum)
2110 			{
2111 				CONTEXT_HANDLE ChannelContext;
2112 
2113 				if (!TsProxyCreateChannelReadResponse(pdu, &ChannelContext, &tsg->ChannelId))
2114 				{
2115 					WLog_ERR(TAG, "TsProxyCreateChannelReadResponse failure");
2116 					return FALSE;
2117 				}
2118 
2119 				if (!tsg->reauthSequence)
2120 					CopyMemory(&tsg->ChannelContext, &ChannelContext, sizeof(CONTEXT_HANDLE));
2121 				else
2122 					CopyMemory(&tsg->NewChannelContext, &ChannelContext, sizeof(CONTEXT_HANDLE));
2123 
2124 				if (!tsg_transition_to_state(tsg, TSG_STATE_CHANNEL_CREATED))
2125 					return FALSE;
2126 
2127 				if (!tsg->reauthSequence)
2128 				{
2129 					if (!TsProxySetupReceivePipeWriteRequest(tsg, &tsg->ChannelContext))
2130 					{
2131 						WLog_ERR(TAG, "TsProxySetupReceivePipe failure");
2132 						return FALSE;
2133 					}
2134 				}
2135 				else
2136 				{
2137 					if (!TsProxyCloseChannelWriteRequest(tsg, &tsg->NewChannelContext))
2138 					{
2139 						WLog_ERR(TAG, "TsProxyCloseChannelWriteRequest failure");
2140 						return FALSE;
2141 					}
2142 
2143 					if (!TsProxyCloseTunnelWriteRequest(tsg, &tsg->NewTunnelContext))
2144 					{
2145 						WLog_ERR(TAG, "TsProxyCloseTunnelWriteRequest failure");
2146 						return FALSE;
2147 					}
2148 				}
2149 
2150 				rc = tsg_transition_to_state(tsg, TSG_STATE_PIPE_CREATED);
2151 				tsg->reauthSequence = FALSE;
2152 			}
2153 			else
2154 			{
2155 				WLog_ERR(TAG, "TSG_STATE_AUTHORIZED unexpected OpNum: %" PRIu32 "\n", call->OpNum);
2156 			}
2157 
2158 			break;
2159 
2160 		case TSG_STATE_CHANNEL_CREATED:
2161 			break;
2162 
2163 		case TSG_STATE_PIPE_CREATED:
2164 			call = rpc_client_call_find_by_id(rpc->client, pdu->CallId);
2165 
2166 			if (!call)
2167 				return FALSE;
2168 
2169 			if (call->OpNum == TsProxyMakeTunnelCallOpnum)
2170 			{
2171 				if (!TsProxyMakeTunnelCallReadResponse(tsg, pdu))
2172 				{
2173 					WLog_ERR(TAG, "TsProxyMakeTunnelCallReadResponse failure");
2174 					return FALSE;
2175 				}
2176 
2177 				rc = TRUE;
2178 
2179 				if (tsg->ReauthTunnelContext)
2180 					rc = tsg_proxy_reauth(tsg);
2181 			}
2182 			else if (call->OpNum == TsProxyCloseChannelOpnum)
2183 			{
2184 				CONTEXT_HANDLE ChannelContext;
2185 
2186 				if (!TsProxyCloseChannelReadResponse(pdu, &ChannelContext))
2187 				{
2188 					WLog_ERR(TAG, "TsProxyCloseChannelReadResponse failure");
2189 					return FALSE;
2190 				}
2191 
2192 				rc = TRUE;
2193 			}
2194 			else if (call->OpNum == TsProxyCloseTunnelOpnum)
2195 			{
2196 				CONTEXT_HANDLE TunnelContext;
2197 
2198 				if (!TsProxyCloseTunnelReadResponse(pdu, &TunnelContext))
2199 				{
2200 					WLog_ERR(TAG, "TsProxyCloseTunnelReadResponse failure");
2201 					return FALSE;
2202 				}
2203 
2204 				rc = TRUE;
2205 			}
2206 
2207 			break;
2208 
2209 		case TSG_STATE_TUNNEL_CLOSE_PENDING:
2210 		{
2211 			CONTEXT_HANDLE ChannelContext;
2212 
2213 			if (!TsProxyCloseChannelReadResponse(pdu, &ChannelContext))
2214 			{
2215 				WLog_ERR(TAG, "TsProxyCloseChannelReadResponse failure");
2216 				return FALSE;
2217 			}
2218 
2219 			if (!tsg_transition_to_state(tsg, TSG_STATE_CHANNEL_CLOSE_PENDING))
2220 				return FALSE;
2221 
2222 			if (!TsProxyCloseChannelWriteRequest(tsg, NULL))
2223 			{
2224 				WLog_ERR(TAG, "TsProxyCloseChannelWriteRequest failure");
2225 				return FALSE;
2226 			}
2227 
2228 			if (!TsProxyMakeTunnelCallWriteRequest(tsg, &tsg->TunnelContext,
2229 			                                       TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST))
2230 			{
2231 				WLog_ERR(TAG, "TsProxyMakeTunnelCall failure");
2232 				return FALSE;
2233 			}
2234 
2235 			rc = TRUE;
2236 		}
2237 		break;
2238 
2239 		case TSG_STATE_CHANNEL_CLOSE_PENDING:
2240 		{
2241 			CONTEXT_HANDLE TunnelContext;
2242 
2243 			if (!TsProxyCloseTunnelReadResponse(pdu, &TunnelContext))
2244 			{
2245 				WLog_ERR(TAG, "TsProxyCloseTunnelReadResponse failure");
2246 				return FALSE;
2247 			}
2248 
2249 			rc = tsg_transition_to_state(tsg, TSG_STATE_FINAL);
2250 		}
2251 		break;
2252 
2253 		case TSG_STATE_FINAL:
2254 			break;
2255 	}
2256 
2257 	return rc;
2258 }
2259 
tsg_check_event_handles(rdpTsg * tsg)2260 BOOL tsg_check_event_handles(rdpTsg* tsg)
2261 {
2262 	if (rpc_client_in_channel_recv(tsg->rpc) < 0)
2263 		return FALSE;
2264 
2265 	if (rpc_client_out_channel_recv(tsg->rpc) < 0)
2266 		return FALSE;
2267 
2268 	return TRUE;
2269 }
2270 
tsg_get_event_handles(rdpTsg * tsg,HANDLE * events,DWORD count)2271 DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events, DWORD count)
2272 {
2273 	UINT32 nCount = 0;
2274 	rdpRpc* rpc = tsg->rpc;
2275 	RpcVirtualConnection* connection = rpc->VirtualConnection;
2276 
2277 	if (events && (nCount < count))
2278 	{
2279 		events[nCount] = rpc->client->PipeEvent;
2280 		nCount++;
2281 	}
2282 	else
2283 		return 0;
2284 
2285 	if (connection->DefaultInChannel && connection->DefaultInChannel->common.tls)
2286 	{
2287 		if (events && (nCount < count))
2288 		{
2289 			BIO_get_event(connection->DefaultInChannel->common.tls->bio, &events[nCount]);
2290 			nCount++;
2291 		}
2292 		else
2293 			return 0;
2294 	}
2295 
2296 	if (connection->NonDefaultInChannel && connection->NonDefaultInChannel->common.tls)
2297 	{
2298 		if (events && (nCount < count))
2299 		{
2300 			BIO_get_event(connection->NonDefaultInChannel->common.tls->bio, &events[nCount]);
2301 			nCount++;
2302 		}
2303 		else
2304 			return 0;
2305 	}
2306 
2307 	if (connection->DefaultOutChannel && connection->DefaultOutChannel->common.tls)
2308 	{
2309 		if (events && (nCount < count))
2310 		{
2311 			BIO_get_event(connection->DefaultOutChannel->common.tls->bio, &events[nCount]);
2312 			nCount++;
2313 		}
2314 		else
2315 			return 0;
2316 	}
2317 
2318 	if (connection->NonDefaultOutChannel && connection->NonDefaultOutChannel->common.tls)
2319 	{
2320 		if (events && (nCount < count))
2321 		{
2322 			BIO_get_event(connection->NonDefaultOutChannel->common.tls->bio, &events[nCount]);
2323 			nCount++;
2324 		}
2325 		else
2326 			return 0;
2327 	}
2328 
2329 	return nCount;
2330 }
2331 
tsg_set_hostname(rdpTsg * tsg,const char * hostname)2332 static BOOL tsg_set_hostname(rdpTsg* tsg, const char* hostname)
2333 {
2334 	free(tsg->Hostname);
2335 	tsg->Hostname = NULL;
2336 	ConvertToUnicode(CP_UTF8, 0, hostname, -1, &tsg->Hostname, 0);
2337 	return TRUE;
2338 }
2339 
tsg_set_machine_name(rdpTsg * tsg,const char * machineName)2340 static BOOL tsg_set_machine_name(rdpTsg* tsg, const char* machineName)
2341 {
2342 	free(tsg->MachineName);
2343 	tsg->MachineName = NULL;
2344 	ConvertToUnicode(CP_UTF8, 0, machineName, -1, &tsg->MachineName, 0);
2345 	return TRUE;
2346 }
2347 
tsg_connect(rdpTsg * tsg,const char * hostname,UINT16 port,DWORD timeout)2348 BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout)
2349 {
2350 	UINT64 looptimeout = timeout * 1000ULL;
2351 	DWORD nCount;
2352 	HANDLE events[MAXIMUM_WAIT_OBJECTS] = { 0 };
2353 	rdpRpc* rpc;
2354 	rdpContext* context;
2355 	rdpSettings* settings;
2356 	rdpTransport* transport;
2357 
2358 	assert(tsg);
2359 
2360 	rpc = tsg->rpc;
2361 	assert(rpc);
2362 
2363 	transport = rpc->transport;
2364 	assert(transport);
2365 
2366 	context = tsg->rpc->context;
2367 	assert(context);
2368 
2369 	settings = context->settings;
2370 
2371 	tsg->Port = port;
2372 	tsg->transport = transport;
2373 
2374 	if (!settings->GatewayPort)
2375 		settings->GatewayPort = 443;
2376 
2377 	if (!tsg_set_hostname(tsg, hostname))
2378 		return FALSE;
2379 
2380 	if (!tsg_set_machine_name(tsg, settings->ComputerName))
2381 		return FALSE;
2382 
2383 	if (!rpc_connect(rpc, timeout))
2384 	{
2385 		WLog_ERR(TAG, "rpc_connect error!");
2386 		return FALSE;
2387 	}
2388 
2389 	nCount = tsg_get_event_handles(tsg, events, ARRAYSIZE(events));
2390 
2391 	if (nCount == 0)
2392 		return FALSE;
2393 
2394 	while (tsg->state != TSG_STATE_PIPE_CREATED)
2395 	{
2396 		const DWORD polltimeout = 250;
2397 		DWORD status = WaitForMultipleObjects(nCount, events, FALSE, polltimeout);
2398 		if (status == WAIT_TIMEOUT)
2399 		{
2400 			if (timeout > 0)
2401 			{
2402 				if (looptimeout < polltimeout)
2403 					return FALSE;
2404 				looptimeout -= polltimeout;
2405 			}
2406 		}
2407 		else
2408 			looptimeout = timeout * 1000ULL;
2409 
2410 		if (!tsg_check_event_handles(tsg))
2411 		{
2412 			WLog_ERR(TAG, "tsg_check failure");
2413 			transport->layer = TRANSPORT_LAYER_CLOSED;
2414 			return FALSE;
2415 		}
2416 	}
2417 
2418 	WLog_INFO(TAG, "TS Gateway Connection Success");
2419 	tsg->bio = BIO_new(BIO_s_tsg());
2420 
2421 	if (!tsg->bio)
2422 		return FALSE;
2423 
2424 	BIO_set_data(tsg->bio, (void*)tsg);
2425 	return TRUE;
2426 }
2427 
tsg_disconnect(rdpTsg * tsg)2428 BOOL tsg_disconnect(rdpTsg* tsg)
2429 {
2430 	/**
2431 	 *                        Gateway Shutdown Phase
2432 	 *
2433 	 *     Client                                              Server
2434 	 *        |                                                   |
2435 	 *        |-------------TsProxyCloseChannel Request---------->|
2436 	 *        |                                                   |
2437 	 *        |<-------TsProxySetupReceivePipe Final Response-----|
2438 	 *        |<-----------TsProxyCloseChannel Response-----------|
2439 	 *        |                                                   |
2440 	 *        |----TsProxyMakeTunnelCall Request (cancel async)-->|
2441 	 *        |                                                   |
2442 	 *        |<---TsProxyMakeTunnelCall Response (call async)----|
2443 	 *        |<---TsProxyMakeTunnelCall Response (cancel async)--|
2444 	 *        |                                                   |
2445 	 *        |--------------TsProxyCloseTunnel Request---------->|
2446 	 *        |<-------------TsProxyCloseTunnel Response----------|
2447 	 *        |                                                   |
2448 	 */
2449 	if (!tsg)
2450 		return FALSE;
2451 
2452 	if (tsg->state != TSG_STATE_TUNNEL_CLOSE_PENDING)
2453 	{
2454 		if (!TsProxyCloseChannelWriteRequest(tsg, &tsg->ChannelContext))
2455 			return FALSE;
2456 
2457 		return tsg_transition_to_state(tsg, TSG_STATE_CHANNEL_CLOSE_PENDING);
2458 	}
2459 
2460 	return TRUE;
2461 }
2462 
2463 /**
2464  * @brief
2465  *
2466  * @param[in] tsg
2467  * @param[in] data
2468  * @param[in] length
2469  * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 bytes to read
2470  */
2471 
tsg_read(rdpTsg * tsg,BYTE * data,size_t length)2472 static int tsg_read(rdpTsg* tsg, BYTE* data, size_t length)
2473 {
2474 	rdpRpc* rpc;
2475 	int status = 0;
2476 
2477 	if (!tsg || !data)
2478 		return -1;
2479 
2480 	rpc = tsg->rpc;
2481 
2482 	if (rpc->transport->layer == TRANSPORT_LAYER_CLOSED)
2483 	{
2484 		WLog_ERR(TAG, "tsg_read error: connection lost");
2485 		return -1;
2486 	}
2487 
2488 	do
2489 	{
2490 		status = rpc_client_receive_pipe_read(rpc->client, data, length);
2491 
2492 		if (status < 0)
2493 			return -1;
2494 
2495 		if (!status && !rpc->transport->blocking)
2496 			return 0;
2497 
2498 		if (rpc->transport->layer == TRANSPORT_LAYER_CLOSED)
2499 		{
2500 			WLog_ERR(TAG, "tsg_read error: connection lost");
2501 			return -1;
2502 		}
2503 
2504 		if (status > 0)
2505 			break;
2506 
2507 		if (rpc->transport->blocking)
2508 		{
2509 			while (WaitForSingleObject(rpc->client->PipeEvent, 0) != WAIT_OBJECT_0)
2510 			{
2511 				if (!tsg_check_event_handles(tsg))
2512 					return -1;
2513 
2514 				WaitForSingleObject(rpc->client->PipeEvent, 100);
2515 			}
2516 		}
2517 	} while (rpc->transport->blocking);
2518 
2519 	return status;
2520 }
2521 
tsg_write(rdpTsg * tsg,const BYTE * data,UINT32 length)2522 static int tsg_write(rdpTsg* tsg, const BYTE* data, UINT32 length)
2523 {
2524 	int status;
2525 
2526 	if (!tsg || !data || !tsg->rpc || !tsg->rpc->transport)
2527 		return -1;
2528 
2529 	if (tsg->rpc->transport->layer == TRANSPORT_LAYER_CLOSED)
2530 	{
2531 		WLog_ERR(TAG, "error, connection lost");
2532 		return -1;
2533 	}
2534 
2535 	status = TsProxySendToServer((handle_t)tsg, data, 1, &length);
2536 
2537 	if (status < 0)
2538 		return -1;
2539 
2540 	return (int)length;
2541 }
2542 
tsg_new(rdpTransport * transport)2543 rdpTsg* tsg_new(rdpTransport* transport)
2544 {
2545 	rdpTsg* tsg;
2546 	tsg = (rdpTsg*)calloc(1, sizeof(rdpTsg));
2547 
2548 	if (!tsg)
2549 		return NULL;
2550 
2551 	tsg->transport = transport;
2552 	tsg->rpc = rpc_new(tsg->transport);
2553 
2554 	if (!tsg->rpc)
2555 		goto out_free;
2556 
2557 	return tsg;
2558 out_free:
2559 	free(tsg);
2560 	return NULL;
2561 }
2562 
tsg_free(rdpTsg * tsg)2563 void tsg_free(rdpTsg* tsg)
2564 {
2565 	if (tsg)
2566 	{
2567 		rpc_free(tsg->rpc);
2568 		free(tsg->Hostname);
2569 		free(tsg->MachineName);
2570 		free(tsg);
2571 	}
2572 }
2573 
transport_bio_tsg_write(BIO * bio,const char * buf,int num)2574 static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
2575 {
2576 	int status;
2577 	rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
2578 	BIO_clear_flags(bio, BIO_FLAGS_WRITE);
2579 
2580 	if (num < 0)
2581 		return -1;
2582 	status = tsg_write(tsg, (const BYTE*)buf, (UINT32)num);
2583 
2584 	if (status < 0)
2585 	{
2586 		BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2587 		return -1;
2588 	}
2589 	else if (status == 0)
2590 	{
2591 		BIO_set_flags(bio, BIO_FLAGS_WRITE);
2592 		WSASetLastError(WSAEWOULDBLOCK);
2593 	}
2594 	else
2595 	{
2596 		BIO_set_flags(bio, BIO_FLAGS_WRITE);
2597 	}
2598 
2599 	return status >= 0 ? status : -1;
2600 }
2601 
transport_bio_tsg_read(BIO * bio,char * buf,int size)2602 static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
2603 {
2604 	int status;
2605 	rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
2606 
2607 	if (!tsg || (size < 0))
2608 	{
2609 		BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2610 		return -1;
2611 	}
2612 
2613 	BIO_clear_flags(bio, BIO_FLAGS_READ);
2614 	status = tsg_read(tsg, (BYTE*)buf, (size_t)size);
2615 
2616 	if (status < 0)
2617 	{
2618 		BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2619 		return -1;
2620 	}
2621 	else if (status == 0)
2622 	{
2623 		BIO_set_flags(bio, BIO_FLAGS_READ);
2624 		WSASetLastError(WSAEWOULDBLOCK);
2625 	}
2626 	else
2627 	{
2628 		BIO_set_flags(bio, BIO_FLAGS_READ);
2629 	}
2630 
2631 	return status > 0 ? status : -1;
2632 }
2633 
transport_bio_tsg_puts(BIO * bio,const char * str)2634 static int transport_bio_tsg_puts(BIO* bio, const char* str)
2635 {
2636 	WINPR_UNUSED(bio);
2637 	WINPR_UNUSED(str);
2638 	return 1;
2639 }
2640 
transport_bio_tsg_gets(BIO * bio,char * str,int size)2641 static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
2642 {
2643 	WINPR_UNUSED(bio);
2644 	WINPR_UNUSED(str);
2645 	WINPR_UNUSED(size);
2646 	return 1;
2647 }
2648 
transport_bio_tsg_ctrl(BIO * bio,int cmd,long arg1,void * arg2)2649 static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
2650 {
2651 	long status = -1;
2652 	rdpTsg* tsg = (rdpTsg*)BIO_get_data(bio);
2653 	RpcVirtualConnection* connection = tsg->rpc->VirtualConnection;
2654 	RpcInChannel* inChannel = connection->DefaultInChannel;
2655 	RpcOutChannel* outChannel = connection->DefaultOutChannel;
2656 
2657 	switch (cmd)
2658 	{
2659 		case BIO_CTRL_FLUSH:
2660 			(void)BIO_flush(inChannel->common.tls->bio);
2661 			(void)BIO_flush(outChannel->common.tls->bio);
2662 			status = 1;
2663 			break;
2664 
2665 		case BIO_C_GET_EVENT:
2666 			if (arg2)
2667 			{
2668 				*((HANDLE*)arg2) = tsg->rpc->client->PipeEvent;
2669 				status = 1;
2670 			}
2671 
2672 			break;
2673 
2674 		case BIO_C_SET_NONBLOCK:
2675 			status = 1;
2676 			break;
2677 
2678 		case BIO_C_READ_BLOCKED:
2679 		{
2680 			BIO* cbio = outChannel->common.bio;
2681 			status = BIO_read_blocked(cbio);
2682 		}
2683 		break;
2684 
2685 		case BIO_C_WRITE_BLOCKED:
2686 		{
2687 			BIO* cbio = inChannel->common.bio;
2688 			status = BIO_write_blocked(cbio);
2689 		}
2690 		break;
2691 
2692 		case BIO_C_WAIT_READ:
2693 		{
2694 			int timeout = (int)arg1;
2695 			BIO* cbio = outChannel->common.bio;
2696 
2697 			if (BIO_read_blocked(cbio))
2698 				return BIO_wait_read(cbio, timeout);
2699 			else if (BIO_write_blocked(cbio))
2700 				return BIO_wait_write(cbio, timeout);
2701 			else
2702 				status = 1;
2703 		}
2704 		break;
2705 
2706 		case BIO_C_WAIT_WRITE:
2707 		{
2708 			int timeout = (int)arg1;
2709 			BIO* cbio = inChannel->common.bio;
2710 
2711 			if (BIO_write_blocked(cbio))
2712 				status = BIO_wait_write(cbio, timeout);
2713 			else if (BIO_read_blocked(cbio))
2714 				status = BIO_wait_read(cbio, timeout);
2715 			else
2716 				status = 1;
2717 		}
2718 		break;
2719 
2720 		default:
2721 			break;
2722 	}
2723 
2724 	return status;
2725 }
2726 
transport_bio_tsg_new(BIO * bio)2727 static int transport_bio_tsg_new(BIO* bio)
2728 {
2729 	assert(bio);
2730 	BIO_set_init(bio, 1);
2731 	BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
2732 	return 1;
2733 }
2734 
transport_bio_tsg_free(BIO * bio)2735 static int transport_bio_tsg_free(BIO* bio)
2736 {
2737 	assert(bio);
2738 	WINPR_UNUSED(bio);
2739 	return 1;
2740 }
2741 
BIO_s_tsg(void)2742 BIO_METHOD* BIO_s_tsg(void)
2743 {
2744 	static BIO_METHOD* bio_methods = NULL;
2745 
2746 	if (bio_methods == NULL)
2747 	{
2748 		if (!(bio_methods = BIO_meth_new(BIO_TYPE_TSG, "TSGateway")))
2749 			return NULL;
2750 
2751 		BIO_meth_set_write(bio_methods, transport_bio_tsg_write);
2752 		BIO_meth_set_read(bio_methods, transport_bio_tsg_read);
2753 		BIO_meth_set_puts(bio_methods, transport_bio_tsg_puts);
2754 		BIO_meth_set_gets(bio_methods, transport_bio_tsg_gets);
2755 		BIO_meth_set_ctrl(bio_methods, transport_bio_tsg_ctrl);
2756 		BIO_meth_set_create(bio_methods, transport_bio_tsg_new);
2757 		BIO_meth_set_destroy(bio_methods, transport_bio_tsg_free);
2758 	}
2759 
2760 	return bio_methods;
2761 }
2762 
tsg_get_state(rdpTsg * tsg)2763 TSG_STATE tsg_get_state(rdpTsg* tsg)
2764 {
2765 	if (!tsg)
2766 		return TSG_STATE_INITIAL;
2767 
2768 	return tsg->state;
2769 }
2770 
tsg_get_bio(rdpTsg * tsg)2771 BIO* tsg_get_bio(rdpTsg* tsg)
2772 {
2773 	if (!tsg)
2774 		return NULL;
2775 
2776 	return tsg->bio;
2777 }
2778 
tsg_set_state(rdpTsg * tsg,TSG_STATE state)2779 BOOL tsg_set_state(rdpTsg* tsg, TSG_STATE state)
2780 {
2781 	if (!tsg)
2782 		return FALSE;
2783 
2784 	tsg->state = state;
2785 	return TRUE;
2786 }
2787