1 /* -*- c-basic-offset: 8 -*-
2    rdesktop: A Remote Desktop Protocol client.
3    Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
4    Copyright 2004-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
5    Copyright 2010-2017 Henrik Andersson <hean01@cendio.se> for Cendio AB
6    Copyright 2017-2019 Karl Mikaelsson <derfian@cendio.se> for Cendio AB
7    Copyright 2016, 2018 Alexander Zakharov <uglym8@gmail.com>
8 
9    This program is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 /*
24   Here are some resources, for your IRP hacking pleasure:
25 
26   http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/winddk.h?view=markup
27 
28   http://win32.mvps.org/ntfs/streams.cpp
29 
30   http://www.acc.umu.se/~bosse/ntifs.h
31 
32   http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/
33 
34   http://us1.samba.org/samba/ftp/specs/smb-nt01.txt
35 
36   http://www.osronline.com/
37 */
38 
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <sys/time.h>
42 #include <dirent.h>		/* opendir, closedir, readdir */
43 #include <time.h>
44 #include <errno.h>
45 #include "rdesktop.h"
46 
47 #define IRP_MJ_CREATE			0x00
48 #define IRP_MJ_CLOSE			0x02
49 #define IRP_MJ_READ			0x03
50 #define IRP_MJ_WRITE			0x04
51 #define	IRP_MJ_QUERY_INFORMATION	0x05
52 #define IRP_MJ_SET_INFORMATION		0x06
53 #define IRP_MJ_QUERY_VOLUME_INFORMATION	0x0a
54 #define IRP_MJ_DIRECTORY_CONTROL	0x0c
55 #define IRP_MJ_DEVICE_CONTROL		0x0e
56 #define IRP_MJ_LOCK_CONTROL             0x11
57 
58 #define IRP_MN_QUERY_DIRECTORY          0x01
59 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02
60 
61 extern char g_hostname[16];
62 extern DEVICE_FNS serial_fns;
63 extern DEVICE_FNS printer_fns;
64 extern DEVICE_FNS parallel_fns;
65 extern DEVICE_FNS disk_fns;
66 #ifdef WITH_SCARD
67 extern DEVICE_FNS scard_fns;
68 #endif
69 extern FILEINFO g_fileinfo[];
70 extern RD_BOOL g_notify_stamp;
71 
72 static VCHANNEL *rdpdr_channel;
73 static uint32 g_epoch;
74 
75 /* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */
76 RD_NTHANDLE g_min_timeout_fd;
77 uint32 g_num_devices;
78 
79 uint32 g_client_id;
80 
81 /* Table with information about rdpdr devices */
82 RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES];
83 char *g_rdpdr_clientname = NULL;
84 
85 /* Used to store incoming io request, until they are ready to be completed */
86 /* using a linked list ensures that they are processed in the right order, */
87 /* if multiple IOs are being done on the same FD */
88 struct async_iorequest
89 {
90 	uint32 fd, major, minor, device, id, length, partial_len;
91 	uint64 offset;
92 	long timeout,		/* Total timeout */
93 	  itv_timeout;		/* Interval timeout (between serial characters) */
94 	uint8 *buffer;
95 	DEVICE_FNS *fns;
96 
97 	struct async_iorequest *next;	/* next element in list */
98 };
99 
100 struct async_iorequest *g_iorequest;
101 
102 /* Return device_id for a given handle */
103 int
get_device_index(RD_NTHANDLE handle)104 get_device_index(RD_NTHANDLE handle)
105 {
106 	int i;
107 	for (i = 0; i < RDPDR_MAX_DEVICES; i++)
108 	{
109 		if (g_rdpdr_device[i].handle == handle)
110 			return i;
111 	}
112 	return -1;
113 }
114 
115 /* Converts a windows path to a unix path */
116 void
convert_to_unix_filename(char * filename)117 convert_to_unix_filename(char *filename)
118 {
119 	char *p;
120 
121 	while ((p = strchr(filename, '\\')))
122 	{
123 		*p = '/';
124 	}
125 }
126 
127 static RD_BOOL
rdpdr_handle_ok(uint32 device,RD_NTHANDLE handle)128 rdpdr_handle_ok(uint32 device, RD_NTHANDLE handle)
129 {
130 	switch (g_rdpdr_device[device].device_type)
131 	{
132 		case DEVICE_TYPE_PARALLEL:
133 		case DEVICE_TYPE_SERIAL:
134 		case DEVICE_TYPE_PRINTER:
135 		case DEVICE_TYPE_SCARD:
136 			if (g_rdpdr_device[device].handle != handle)
137 				return False;
138 			break;
139 		case DEVICE_TYPE_DISK:
140 			if (g_fileinfo[handle].device_id != device)
141 				return False;
142 			break;
143 	}
144 	return True;
145 }
146 
147 /* Add a new io request to the table containing pending io requests so it won't block rdesktop */
148 static RD_BOOL
add_async_iorequest(uint32 device,uint32 file,uint32 id,uint32 major,uint32 length,DEVICE_FNS * fns,uint32 total_timeout,uint32 interval_timeout,uint8 * buffer,uint64 offset)149 add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length,
150 		    DEVICE_FNS * fns, uint32 total_timeout, uint32 interval_timeout, uint8 * buffer,
151 		    uint64 offset)
152 {
153 	struct async_iorequest *iorq;
154 
155 	if (g_iorequest == NULL)
156 	{
157 		g_iorequest = (struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
158 		if (!g_iorequest)
159 			return False;
160 		g_iorequest->fd = 0;
161 		g_iorequest->next = NULL;
162 	}
163 
164 	iorq = g_iorequest;
165 
166 	while (iorq->fd != 0)
167 	{
168 		/* create new element if needed */
169 		if (iorq->next == NULL)
170 		{
171 			iorq->next =
172 				(struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
173 			if (!iorq->next)
174 				return False;
175 			iorq->next->fd = 0;
176 			iorq->next->next = NULL;
177 		}
178 		iorq = iorq->next;
179 	}
180 	iorq->device = device;
181 	iorq->fd = file;
182 	iorq->id = id;
183 	iorq->major = major;
184 	iorq->length = length;
185 	iorq->partial_len = 0;
186 	iorq->fns = fns;
187 	iorq->timeout = total_timeout;
188 	iorq->itv_timeout = interval_timeout;
189 	iorq->buffer = buffer;
190 	iorq->offset = offset;
191 	return True;
192 }
193 
194 static void
rdpdr_send_client_announce_reply(void)195 rdpdr_send_client_announce_reply(void)
196 {
197 	/* DR_CORE_CLIENT_ANNOUNCE_RSP */
198 	STREAM s;
199 	s = channel_init(rdpdr_channel, 12);
200 	out_uint16_le(s, RDPDR_CTYP_CORE);
201 	out_uint16_le(s, PAKID_CORE_CLIENTID_CONFIRM);
202 	out_uint16_le(s, 1);	/* VersionMajor, MUST be set to 0x1 */
203 	out_uint16_le(s, 5);	/* VersionMinor */
204 	out_uint32_be(s, g_client_id);	/* ClientID */
205 	s_mark_end(s);
206 	channel_send(s, rdpdr_channel);
207 	s_free(s);
208 }
209 
210 
211 static void
rdpdr_send_client_name_request(void)212 rdpdr_send_client_name_request(void)
213 {
214 	/* DR_CORE_CLIENT_NAME_REQ */
215 	STREAM s;
216 	struct stream name = { 0 };
217 
218 	if (NULL == g_rdpdr_clientname)
219 	{
220 		g_rdpdr_clientname = g_hostname;
221 	}
222 
223 	s_realloc(&name, 512 * 4);
224 	s_reset(&name);
225 	out_utf16s(&name, g_rdpdr_clientname);
226 	s_mark_end(&name);
227 
228 	s = channel_init(rdpdr_channel, 16 + s_length(&name));
229 	out_uint16_le(s, RDPDR_CTYP_CORE);
230 	out_uint16_le(s, PAKID_CORE_CLIENT_NAME);
231 	out_uint32_le(s, 1);	/* UnicodeFlag */
232 	out_uint32_le(s, 0);	/* CodePage */
233 	out_uint32_le(s, s_length(&name));	/* ComputerNameLen */
234 	out_stream(s, &name);
235 	s_mark_end(s);
236 	channel_send(s, rdpdr_channel);
237 	s_free(s);
238 }
239 
240 /* Returns the size of the payload of the announce packet */
241 static size_t
announcedata_size()242 announcedata_size()
243 {
244 	size_t size, i;
245 	PRINTER *printerinfo;
246 	DISK_DEVICE *diskinfo;
247 
248 	size = 8;		/* Header + DeviceCount */
249 
250 	for (i = 0; i < g_num_devices; i++)
251 	{
252 		size += 4;	/* DeviceType */
253 		size += 4;	/* DeviceId */
254 		size += 8;	/* PreferredDosName */
255 		size += 4;	/* DeviceDataLength */
256 
257 		switch (g_rdpdr_device[i].device_type)
258 		{
259 			case DEVICE_TYPE_DISK:
260 				diskinfo = (DISK_DEVICE *) g_rdpdr_device[i].pdevice_data;
261 				size += 2 * strlen(diskinfo->name) + 2;
262 				break;
263 			case DEVICE_TYPE_PRINTER:
264 				printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
265 				printerinfo->bloblen =
266 					printercache_load_blob(printerinfo->printer,
267 							       &(printerinfo->blob));
268 
269 				size += 0x18;
270 				size += 2 * strlen(printerinfo->driver) + 2;
271 				size += 2 * strlen(printerinfo->printer) + 2;
272 				size += printerinfo->bloblen;
273 				break;
274 			default:
275 				break;
276 		}
277 	}
278 
279 	return size;
280 }
281 
282 static void
rdpdr_send_client_device_list_announce(void)283 rdpdr_send_client_device_list_announce(void)
284 {
285 	/* DR_CORE_CLIENT_ANNOUNCE_RSP */
286 	uint32 bloblen, disklen, flags;
287 	size_t i;
288 	STREAM s;
289 	PRINTER *printerinfo;
290 	DISK_DEVICE *diskinfo;
291 	struct stream drv = { 0 }, prt =
292 	{
293 	0};
294 
295 	s = channel_init(rdpdr_channel, announcedata_size());
296 	out_uint16_le(s, RDPDR_CTYP_CORE);
297 	out_uint16_le(s, PAKID_CORE_DEVICE_LIST_ANNOUNCE);
298 
299 	out_uint32_le(s, g_num_devices);
300 
301 	for (i = 0; i < g_num_devices; i++)	/* DEVICE_ANNOUNCE */
302 	{
303 		out_uint32_le(s, g_rdpdr_device[i].device_type);
304 		out_uint32_le(s, i);	/* RDP Device ID */
305 		out_uint8a(s, g_rdpdr_device[i].name, 8);	/* preferredDosName, limited to 8 characters */
306 		switch (g_rdpdr_device[i].device_type)
307 		{
308 			case DEVICE_TYPE_DISK:
309 				diskinfo = (DISK_DEVICE *) g_rdpdr_device[i].pdevice_data;
310 
311 				/* The RDP specification says that the DeviceData is supposed to be
312 				   a null-terminated Unicode string, but that does not work. In
313 				   practice the string is expected to be an ASCII string, like a
314 				   variable-length preferredDosName. */
315 
316 				disklen = strlen(diskinfo->name) + 1;
317 
318 				out_uint32_le(s, disklen);	/* DeviceDataLength */
319 				out_uint8a(s, diskinfo->name, disklen);	/* DeviceData */
320 				break;
321 
322 			case DEVICE_TYPE_PRINTER:
323 				printerinfo = (PRINTER *) g_rdpdr_device[i].pdevice_data;
324 
325 				s_realloc(&prt, 512 * 4);
326 				s_reset(&prt);
327 				out_utf16s(&prt, printerinfo->printer);
328 				s_mark_end(&prt);
329 
330 				s_realloc(&drv, 512 * 4);
331 				s_reset(&drv);
332 				out_utf16s(&drv, printerinfo->driver);
333 				s_mark_end(&drv);
334 
335 				bloblen = printerinfo->bloblen;
336 				flags = 0;
337 				if (printerinfo->default_printer)
338 					flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
339 
340 				out_uint32_le(s, 24 + s_length(&drv) + s_length(&prt) + bloblen);	/* DeviceDataLength */
341 				out_uint32_le(s, flags);	/* Flags */
342 				out_uint32_le(s, 0);	/* Codepage */
343 				out_uint32_le(s, 0);	/* PnPNameLen */
344 				out_uint32_le(s, s_length(&drv));	/* DriverNameLen */
345 				out_uint32_le(s, s_length(&prt));	/* PrinterNameLen */
346 				out_uint32_le(s, bloblen);	/* CachedFieldsLen */
347 				// out_uint8s(s, 0);       /* PnPName (Skipped) */
348 				out_stream(s, &drv);	/* DriverName */
349 				out_stream(s, &prt);	/* PrinterName */
350 				out_uint8a(s, printerinfo->blob, bloblen);	/* CachedPrinterConfigData */
351 
352 				if (printerinfo->blob)
353 					xfree(printerinfo->blob);	/* Blob is sent twice if reconnecting */
354 				break;
355 			default:
356 				out_uint32(s, 0);
357 		}
358 	}
359 
360 	s_mark_end(s);
361 	channel_send(s, rdpdr_channel);
362 	s_free(s);
363 }
364 
365 void
rdpdr_send_completion(uint32 device,uint32 id,uint32 status,uint32 result,uint8 * buffer,uint32 length)366 rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer,
367 		      uint32 length)
368 {
369 	STREAM s;
370 
371 #ifdef WITH_SCARD
372 	scard_lock(SCARD_LOCK_RDPDR);
373 #endif
374 	if (status == RD_STATUS_BUFFER_TOO_SMALL) {
375 		/*
376 		 * Not enough space has been allocated by server to store the result.
377 		 * Send STATUS_BUFFER_TOO_SMALL error as a IoStatus.
378 		 */
379 		result = 0;
380 		length = 0;
381 	}
382 
383 	s = channel_init(rdpdr_channel, 20 + length);
384 	out_uint16_le(s, RDPDR_CTYP_CORE);
385 	out_uint16_le(s, PAKID_CORE_DEVICE_IOCOMPLETION);
386 	out_uint32_le(s, device);
387 	out_uint32_le(s, id);
388 	out_uint32_le(s, status);
389 	out_uint32_le(s, result);
390 	if (length)
391 		out_uint8a(s, buffer, length);
392 	s_mark_end(s);
393 
394 	logger(Protocol, Debug, "rdpdr_send_completion()");
395 	/* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
396 
397 	channel_send(s, rdpdr_channel);
398 	s_free(s);
399 #ifdef WITH_SCARD
400 	scard_unlock(SCARD_LOCK_RDPDR);
401 #endif
402 }
403 
404 /* Processes a DR_DEVICE_IOREQUEST (minus the leading header field) */
405 static void
rdpdr_process_irp(STREAM s)406 rdpdr_process_irp(STREAM s)
407 {
408 	uint32 result = 0,
409 		length = 0,
410 		desired_access = 0,
411 		request,
412 		file,
413 		info_level,
414 		id,
415 		major,
416 		minor,
417 		device,
418 		bytes_out,
419 		share_mode, disposition, total_timeout, interval_timeout, flags_and_attributes = 0;
420 
421 	uint64 offset;
422 
423 	char *filename;
424 	uint32 filename_len;
425 
426 	uint8 *pst_buf;
427 	STREAM out;
428 	DEVICE_FNS *fns;
429 	RD_BOOL rw_blocking = True;
430 	RD_NTSTATUS status = RD_STATUS_INVALID_DEVICE_REQUEST;
431 
432 	in_uint32_le(s, device);
433 	in_uint32_le(s, file);
434 	in_uint32_le(s, id);
435 	in_uint32_le(s, major);
436 	in_uint32_le(s, minor);
437 
438 	filename = NULL;
439 
440 	out = NULL;
441 
442 	if (device >= RDPDR_MAX_DEVICES)
443 	{
444 		logger(Protocol, Error,
445 		       "rdpdr_process_irp(), invalid irp device=0x%lx, file=0x%lx, id=0x%lx, major=0x%lx, minor=0x%lx",
446 		       device, file, id, major, minor);
447 		return;
448 	}
449 
450 	switch (g_rdpdr_device[device].device_type)
451 	{
452 		case DEVICE_TYPE_SERIAL:
453 
454 			fns = &serial_fns;
455 			rw_blocking = False;
456 			break;
457 
458 		case DEVICE_TYPE_PARALLEL:
459 
460 			fns = &parallel_fns;
461 			rw_blocking = False;
462 			break;
463 
464 		case DEVICE_TYPE_PRINTER:
465 
466 			fns = &printer_fns;
467 			break;
468 
469 		case DEVICE_TYPE_DISK:
470 
471 			fns = &disk_fns;
472 			rw_blocking = False;
473 			break;
474 
475 		case DEVICE_TYPE_SCARD:
476 #ifdef WITH_SCARD
477 			fns = &scard_fns;
478 			rw_blocking = False;
479 			break;
480 #endif
481 		default:
482 			logger(Protocol, Error,
483 			       "rdpdr_process_irp(), received IRP for unknown device type %ld",
484 			       device);
485 			return;
486 	}
487 
488 	switch (major)
489 	{
490 		case IRP_MJ_CREATE:
491 
492 			in_uint32_be(s, desired_access);
493 			in_uint8s(s, 0x08);	/* unknown */
494 			in_uint8s(s, 4);	/* skip error_mode */
495 			in_uint32_le(s, share_mode);
496 			in_uint32_le(s, disposition);
497 			in_uint32_le(s, flags_and_attributes);
498 			in_uint32_le(s, length);
499 
500 			if (length && (length / 2) < 256)
501 			{
502 				rdp_in_unistr(s, length, &filename, &filename_len);
503 				if (filename)
504 					convert_to_unix_filename(filename);
505 			}
506 
507 			if (!fns->create)
508 			{
509 				status = RD_STATUS_NOT_SUPPORTED;
510 				free(filename);
511 				break;
512 			}
513 
514 			status = fns->create(device, desired_access, share_mode, disposition,
515 					     flags_and_attributes, filename, &result);
516 
517 			free(filename);
518 			out = s_alloc(1);
519 			out_uint8(out, 0);
520 			s_mark_end(out);
521 			break;
522 
523 		case IRP_MJ_CLOSE:
524 			if (!fns->close)
525 			{
526 				status = RD_STATUS_NOT_SUPPORTED;
527 				break;
528 			}
529 
530 			status = fns->close(file);
531 			break;
532 
533 		case IRP_MJ_READ:
534 
535 			if (!fns->read)
536 			{
537 				status = RD_STATUS_NOT_SUPPORTED;
538 				break;
539 			}
540 
541 			in_uint32_le(s, length);
542 			in_uint64_le(s, offset);
543 			in_uint8s(s, 20); 	   /* 20 bytes of padding */
544 
545 			logger(Protocol, Debug,
546 			       "rdpdr_process_irp(), IRP Read length=%d, offset=%ld",
547 			       length, offset);
548 
549 			if (!rdpdr_handle_ok(device, file))
550 			{
551 				status = RD_STATUS_INVALID_HANDLE;
552 				break;
553 			}
554 
555 			if (rw_blocking)	/* Complete read immediately */
556 			{
557 				uint8* buffer;
558 				out = s_alloc(length);
559 				out_uint8p(out, buffer, length);
560 				status = fns->read(file, buffer, length, offset, &result);
561 				/* Might have read less */
562 				s_mark_end(out);
563 				s_seek(out, result);
564 				s_mark_end(out);
565 				break;
566 			}
567 
568 			/* Add request to table */
569 			pst_buf = (uint8 *) xmalloc(length);
570 			if (!pst_buf)
571 			{
572 				status = RD_STATUS_CANCELLED;
573 				break;
574 			}
575 			serial_get_timeout(file, length, &total_timeout, &interval_timeout);
576 			if (add_async_iorequest
577 			    (device, file, id, major, length, fns, total_timeout, interval_timeout,
578 			     pst_buf, offset))
579 			{
580 				status = RD_STATUS_PENDING;
581 				break;
582 			}
583 
584 			status = RD_STATUS_CANCELLED;
585 			break;
586 		case IRP_MJ_WRITE:
587 
588 			out = s_alloc(1);
589 			out_uint8(out, 0);
590 			s_mark_end(out);
591 
592 			if (!fns->write)
593 			{
594 				status = RD_STATUS_NOT_SUPPORTED;
595 				break;
596 			}
597 
598 			in_uint32_le(s, length);
599 			in_uint64_le(s, offset);
600 			in_uint8s(s, 20);        /* 20 bytes of padding before WriteData */
601 
602 			logger(Protocol, Debug,
603 			       "rdpdr_process_irp(), IRP Write length=%d, offset=%ld",
604 			       result, offset);
605 
606 			if (!rdpdr_handle_ok(device, file))
607 			{
608 				status = RD_STATUS_INVALID_HANDLE;
609 				break;
610 			}
611 
612 			if (rw_blocking)	/* Complete immediately */
613 			{
614 				unsigned char *data;
615 				in_uint8p(s, data, length);
616 				status = fns->write(file, data, length, offset, &result);
617 				break;
618 			}
619 
620 			/* Add to table */
621 			pst_buf = (uint8 *) xmalloc(length);
622 			if (!pst_buf)
623 			{
624 				status = RD_STATUS_CANCELLED;
625 				break;
626 			}
627 
628 			in_uint8a(s, pst_buf, length);
629 
630 			if (add_async_iorequest
631 			    (device, file, id, major, length, fns, 0, 0, pst_buf, offset))
632 			{
633 				status = RD_STATUS_PENDING;
634 				break;
635 			}
636 
637 			status = RD_STATUS_CANCELLED;
638 			break;
639 
640 		case IRP_MJ_QUERY_INFORMATION:
641 
642 			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
643 			{
644 				status = RD_STATUS_INVALID_HANDLE;
645 				break;
646 			}
647 			in_uint32_le(s, info_level);
648 
649 			out = s_alloc(1024);
650 			status = disk_query_information(file, info_level, out);
651 			s_mark_end(out);
652 			result = s_length(out);
653 
654 			break;
655 
656 		case IRP_MJ_SET_INFORMATION:
657 
658 			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
659 			{
660 				status = RD_STATUS_INVALID_HANDLE;
661 				break;
662 			}
663 
664 			in_uint32_le(s, info_level);
665 
666 			out = s_alloc(1024);
667 			status = disk_set_information(file, info_level, s, out);
668 			s_mark_end(out);
669 			result = s_length(out);
670 			break;
671 
672 		case IRP_MJ_QUERY_VOLUME_INFORMATION:
673 
674 			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
675 			{
676 				status = RD_STATUS_INVALID_HANDLE;
677 				break;
678 			}
679 
680 			in_uint32_le(s, info_level);
681 
682 			out = s_alloc(1024);
683 			status = disk_query_volume_information(file, info_level, out);
684 			s_mark_end(out);
685 			result = s_length(out);
686 			break;
687 
688 		case IRP_MJ_DIRECTORY_CONTROL:
689 
690 			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
691 			{
692 				status = RD_STATUS_INVALID_HANDLE;
693 				break;
694 			}
695 
696 			switch (minor)
697 			{
698 				case IRP_MN_QUERY_DIRECTORY:
699 
700 					in_uint32_le(s, info_level);
701 					in_uint8s(s, 1);
702 					in_uint32_le(s, length);
703 					in_uint8s(s, 0x17);
704 					if (length && length < 2 * 255)
705 					{
706 						rdp_in_unistr(s, length, &filename, &filename_len);
707 						if (filename)
708 							convert_to_unix_filename(filename);
709 					}
710 
711 					out = s_alloc(1024);
712 					status = disk_query_directory(file, info_level, filename,
713 								      out);
714 					s_mark_end(out);
715 					if (!s_length(out))
716 					{
717 						out_uint8(out, 0);
718 						s_mark_end(out);
719 					}
720 					result = s_length(out);
721 
722 					free(filename);
723 					break;
724 
725 				case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
726 
727 					/* JIF
728 					   unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor);  */
729 
730 					in_uint32_le(s, info_level);	/* notify mask */
731 
732 					status = disk_create_notify(file, info_level);
733 					result = 0;
734 
735 					if (status == RD_STATUS_PENDING)
736 						add_async_iorequest(device, file, id, major, length,
737 								    fns, 0, 0, NULL, 0);
738 					break;
739 
740 				default:
741 
742 					status = RD_STATUS_INVALID_PARAMETER;
743 					/* JIF */
744 					logger(Protocol, Warning,
745 					       "rdpdr_process_irp(), unhandled minor opcode, major=0x%x, minor=0x%x",
746 					       major, minor);
747 			}
748 			break;
749 
750 		case IRP_MJ_DEVICE_CONTROL:
751 
752 			if (!fns->device_control)
753 			{
754 				status = RD_STATUS_NOT_SUPPORTED;
755 				break;
756 			}
757 
758 			/* DR_CONTROL_REQ (2.2.1.4.5 of MS-RDPEFS) */
759 			/* OutputBufferLength */
760 			in_uint32_le(s, bytes_out);
761 			in_uint8s(s, 4);	/* skip  bytes_in */
762 			in_uint32_le(s, request);
763 			/* Padding */
764 			in_uint8s(s, 0x14);
765 
766 			/* TODO: Why do we need to increase length by padlen? Or is it hdr len? */
767 			out = s_alloc(bytes_out + 0x14);
768 
769 #ifdef WITH_SCARD
770 			scardSetInfo(g_epoch, device, id, bytes_out + 0x14);
771 #endif
772 			status = fns->device_control(file, request, s, out);
773 			s_mark_end(out);
774 			result = s_length(out);
775 
776 			/* Serial SERIAL_WAIT_ON_MASK */
777 			if (status == RD_STATUS_PENDING)
778 			{
779 				if (add_async_iorequest
780 				    (device, file, id, major, length, fns, 0, 0, NULL, 0))
781 				{
782 					status = RD_STATUS_PENDING;
783 					break;
784 				}
785 			}
786 #ifdef WITH_SCARD
787 			else if (status == (RD_STATUS_PENDING | 0xC0000000))
788 				status = RD_STATUS_PENDING;
789 #endif
790 			break;
791 
792 
793 		case IRP_MJ_LOCK_CONTROL:
794 
795 			if (g_rdpdr_device[device].device_type != DEVICE_TYPE_DISK)
796 			{
797 				status = RD_STATUS_INVALID_HANDLE;
798 				break;
799 			}
800 
801 			in_uint32_le(s, info_level);
802 
803 			out = s_alloc(1024);
804 			/* FIXME: Perhaps consider actually *do*
805 			   something here :-) */
806 			status = RD_STATUS_SUCCESS;
807 			s_mark_end(out);
808 			result = s_length(out);
809 			break;
810 
811 		default:
812 			logger(Protocol, Warning,
813 			       "rdpdr_process_irp(), unhandled major opcode, major=0x%x, minor=0x%x",
814 			       major, minor);
815 			break;
816 	}
817 
818 	if (status != RD_STATUS_PENDING)
819 	{
820 		size_t buffer_len;
821 		uint8 *buffer;
822 
823 		if (out != NULL)
824 		{
825 			buffer_len = s_length(out);
826 			s_seek(out, 0);
827 			in_uint8p(out, buffer, buffer_len);
828 		}
829 		else
830 		{
831 			buffer_len = 0;
832 			buffer = NULL;
833 		}
834 
835 		rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
836 	}
837 	if (out)
838 		s_free(out);
839 }
840 
841 static void
rdpdr_send_client_capability_response(void)842 rdpdr_send_client_capability_response(void)
843 {
844 	/* DR_CORE_CAPABILITY_RSP */
845 	STREAM s;
846 	s = channel_init(rdpdr_channel, 0x50);
847 
848 	out_uint16_le(s, RDPDR_CTYP_CORE);	/* Header */
849 	out_uint16_le(s, PAKID_CORE_CLIENT_CAPABILITY);	/* Header */
850 	out_uint16_le(s, 5);	/* numCapabilities */
851 	out_uint16_le(s, 0);	/* Padding */
852 
853 	out_uint16_le(s, CAP_GENERAL_TYPE);	/* CapabilityType */
854 	out_uint16_le(s, 0x28);	/* CapabilityLength */
855 	out_uint32_le(s, GENERAL_CAPABILITY_VERSION_01);	/* Version */
856 	out_uint32_le(s, 0);	/* osType */
857 	out_uint32_le(s, 0);	/* osVersion */
858 	out_uint16_le(s, 1);	/* protocolMajorVersion */
859 	out_uint16_le(s, 5);	/* protocolMinorVersion */
860 	out_uint32_le(s, ALL_RDPDR_IRP_MJ);	/* ioCode1 */
861 	out_uint32_le(s, 0);	/* ioCode2 */
862 	out_uint32_le(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU);	/* extendedPDU */
863 	out_uint32_le(s, 0);	/* extraFlags1 */
864 	out_uint32_le(s, 0);	/* extraFlags2 */
865 
866 	out_uint16_le(s, CAP_PRINTER_TYPE);	/* CapabilityType */
867 	out_uint16_le(s, 8);	/* CapabilityLength */
868 	out_uint32_le(s, PRINT_CAPABILITY_VERSION_01);	/* Version */
869 
870 	out_uint16_le(s, CAP_PORT_TYPE);	/* CapabilityType */
871 	out_uint16_le(s, 8);	/* CapabilityLength */
872 	out_uint32_le(s, PORT_CAPABILITY_VERSION_01);	/* Version */
873 
874 	out_uint16_le(s, CAP_DRIVE_TYPE);	/* CapabilityType */
875 	out_uint16_le(s, 8);	/* CapabilityLength */
876 	out_uint32_le(s, DRIVE_CAPABILITY_VERSION_02);	/* Version */
877 
878 	out_uint16_le(s, CAP_SMARTCARD_TYPE);	/* CapabilityType */
879 	out_uint16_le(s, 8);	/* CapabilityLength */
880 	out_uint32_le(s, SMARTCARD_CAPABILITY_VERSION_01);	/* Version */
881 
882 	s_mark_end(s);
883 	channel_send(s, rdpdr_channel);
884 	s_free(s);
885 }
886 
887 static void
rdpdr_process(STREAM s)888 rdpdr_process(STREAM s)
889 {
890 	uint32 handle;
891 	uint16 vmin;
892 	uint16 component;
893 	uint16 pakid;
894 
895 	logger(Protocol, Debug, "rdpdr_process()");
896 	/* hexdump(s->p, s_remaining(s)); */
897 
898 	in_uint16(s, component);        /* RDPDR_HEADER.Component */
899 	in_uint16(s, pakid);            /* RDPDR_HEADER.PacketId */
900 
901 	if (component == RDPDR_CTYP_CORE)
902 	{
903 		switch (pakid)
904 		{
905 			case PAKID_CORE_DEVICE_IOREQUEST:
906 				rdpdr_process_irp(s);
907 				break;
908 
909 			case PAKID_CORE_SERVER_ANNOUNCE:
910 				/* DR_CORE_SERVER_ANNOUNCE_REQ */
911 				in_uint8s(s, 2);	/* skip versionMajor */
912 				in_uint16_le(s, vmin);	/* VersionMinor */
913 
914 				in_uint32_le(s, g_client_id);	/* ClientID */
915 
916 				/* The RDP client is responsibility to provide a random client id
917 				   if server version is < 12 */
918 				if (vmin < 0x000c)
919 					g_client_id = 0x815ed39d;	/* IP address (use 127.0.0.1) 0x815ed39d */
920 				g_epoch++;
921 
922 #if WITH_SCARD
923 				/*
924 				 * We need to release all SCARD contexts to end all
925 				 * current transactions and pending calls
926 				 */
927 				scard_release_all_contexts();
928 
929 				/*
930 				 * According to [MS-RDPEFS] 3.2.5.1.2:
931 				 *
932 				 * If this packet appears after a sequence of other packets,
933 				 * it is a signal that the server has reconnected to a new session
934 				 * and the whole sequence has been reset. The client MUST treat
935 				 * this packet as the beginning of a new sequence.
936 				 * The client MUST also cancel all outstanding requests and release
937 				 * previous references to all devices.
938 				 *
939 				 * If any problem arises in the future, please, pay attention to the
940 				 * "If this packet appears after a sequence of other packets" part
941 				 *
942 				 */
943 
944 #endif
945 
946 				rdpdr_send_client_announce_reply();
947 				rdpdr_send_client_name_request();
948 				break;
949 
950 			case PAKID_CORE_CLIENTID_CONFIRM:
951 				rdpdr_send_client_device_list_announce();
952 				break;
953 
954 			case PAKID_CORE_DEVICE_REPLY:
955 				in_uint32(s, handle);
956 				logger(Protocol, Debug,
957 				       "rdpdr_process(), server connected to resource %d", handle);
958 				break;
959 
960 			case PAKID_CORE_SERVER_CAPABILITY:
961 				rdpdr_send_client_capability_response();
962 				break;
963 
964 			default:
965 				logger(Protocol, Debug,
966 				       "rdpdr_process(), pakid 0x%x of component 0x%x", pakid,
967 				       component);
968 				break;
969 
970 		}
971 	}
972 	else if (component == RDPDR_CTYP_PRN)
973 	{
974 		if (pakid == PAKID_PRN_CACHE_DATA)
975 			printercache_process(s);
976 	}
977 	else
978 		logger(Protocol, Warning, "rdpdr_process(), unhandled component 0x%x", component);
979 }
980 
981 RD_BOOL
rdpdr_init()982 rdpdr_init()
983 {
984 	rdpdr_channel =
985 		channel_register("rdpdr",
986 				 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_COMPRESS_RDP,
987 				 rdpdr_process);
988 
989 	return (rdpdr_channel != NULL);
990 }
991 
992 /* Add file descriptors of pending io request to select() */
993 void
rdpdr_add_fds(int * n,fd_set * rfds,fd_set * wfds,struct timeval * tv,RD_BOOL * timeout)994 rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, RD_BOOL * timeout)
995 {
996 	uint32 select_timeout = 0;	/* Timeout value to be used for select() (in milliseconds). */
997 	struct async_iorequest *iorq;
998 	char c;
999 
1000 	iorq = g_iorequest;
1001 	while (iorq != NULL)
1002 	{
1003 		if (iorq->fd != 0)
1004 		{
1005 			switch (iorq->major)
1006 			{
1007 				case IRP_MJ_READ:
1008 					/* Is this FD valid? FDs will
1009 					   be invalid when
1010 					   reconnecting. FIXME: Real
1011 					   support for reconnects. */
1012 
1013 					FD_SET(iorq->fd, rfds);
1014 					*n = MAX(*n, (int) iorq->fd);
1015 
1016 					/* Check if io request timeout is smaller than current (but not 0). */
1017 					if (iorq->timeout
1018 					    && (select_timeout == 0
1019 						|| iorq->timeout < select_timeout))
1020 					{
1021 						/* Set new timeout */
1022 						select_timeout = iorq->timeout;
1023 						g_min_timeout_fd = iorq->fd;	/* Remember fd */
1024 						tv->tv_sec = select_timeout / 1000;
1025 						tv->tv_usec = (select_timeout % 1000) * 1000;
1026 						*timeout = True;
1027 						break;
1028 					}
1029 					if (iorq->itv_timeout && iorq->partial_len > 0
1030 					    && (select_timeout == 0
1031 						|| iorq->itv_timeout < select_timeout))
1032 					{
1033 						/* Set new timeout */
1034 						select_timeout = iorq->itv_timeout;
1035 						g_min_timeout_fd = iorq->fd;	/* Remember fd */
1036 						tv->tv_sec = select_timeout / 1000;
1037 						tv->tv_usec = (select_timeout % 1000) * 1000;
1038 						*timeout = True;
1039 						break;
1040 					}
1041 					break;
1042 
1043 				case IRP_MJ_WRITE:
1044 					/* FD still valid? See above. */
1045 					if ((write(iorq->fd, &c, 0) != 0) && (errno == EBADF))
1046 						break;
1047 
1048 					FD_SET(iorq->fd, wfds);
1049 					*n = MAX(*n, (int) iorq->fd);
1050 					break;
1051 
1052 				case IRP_MJ_DEVICE_CONTROL:
1053 					if (select_timeout > 5)
1054 						select_timeout = 5;	/* serial event queue */
1055 					break;
1056 
1057 			}
1058 
1059 		}
1060 
1061 		iorq = iorq->next;
1062 	}
1063 }
1064 
1065 struct async_iorequest *
rdpdr_remove_iorequest(struct async_iorequest * prev,struct async_iorequest * iorq)1066 rdpdr_remove_iorequest(struct async_iorequest *prev, struct async_iorequest *iorq)
1067 {
1068 	if (!iorq)
1069 		return NULL;
1070 
1071 	if (iorq->buffer)
1072 		xfree(iorq->buffer);
1073 	if (prev)
1074 	{
1075 		prev->next = iorq->next;
1076 		xfree(iorq);
1077 		iorq = prev->next;
1078 	}
1079 	else
1080 	{
1081 		/* Even if NULL */
1082 		g_iorequest = iorq->next;
1083 		xfree(iorq);
1084 		iorq = NULL;
1085 	}
1086 	return iorq;
1087 }
1088 
1089 /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
1090 static void
_rdpdr_check_fds(fd_set * rfds,fd_set * wfds,RD_BOOL timed_out)1091 _rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out)
1092 {
1093 	RD_NTSTATUS status;
1094 	uint32 result = 0;
1095 	DEVICE_FNS *fns;
1096 	struct async_iorequest *iorq;
1097 	struct async_iorequest *prev;
1098 	uint32 req_size = 0;
1099 	uint32 buffer_len;
1100 	struct stream out;
1101 	uint8 *buffer = NULL;
1102 
1103 
1104 	if (timed_out)
1105 	{
1106 		/* check serial iv_timeout */
1107 
1108 		iorq = g_iorequest;
1109 		prev = NULL;
1110 		while (iorq != NULL)
1111 		{
1112 			if (iorq->fd == g_min_timeout_fd)
1113 			{
1114 				if ((iorq->partial_len > 0) &&
1115 				    (g_rdpdr_device[iorq->device].device_type ==
1116 				     DEVICE_TYPE_SERIAL))
1117 				{
1118 
1119 					/* iv_timeout between 2 chars, send partial_len */
1120 					/*printf("RDPDR: IVT total %u bytes read of %u\n", iorq->partial_len, iorq->length); */
1121 					rdpdr_send_completion(iorq->device,
1122 							      iorq->id, RD_STATUS_SUCCESS,
1123 							      iorq->partial_len,
1124 							      iorq->buffer, iorq->partial_len);
1125 					iorq = rdpdr_remove_iorequest(prev, iorq);
1126 					return;
1127 				}
1128 				else
1129 				{
1130 					break;
1131 				}
1132 
1133 			}
1134 			else
1135 			{
1136 				break;
1137 			}
1138 
1139 
1140 			prev = iorq;
1141 			if (iorq)
1142 				iorq = iorq->next;
1143 
1144 		}
1145 
1146 		rdpdr_abort_io(g_min_timeout_fd, 0, RD_STATUS_TIMEOUT);
1147 		return;
1148 	}
1149 
1150 	iorq = g_iorequest;
1151 	prev = NULL;
1152 	while (iorq != NULL)
1153 	{
1154 		if (iorq->fd != 0)
1155 		{
1156 			switch (iorq->major)
1157 			{
1158 				case IRP_MJ_READ:
1159 					if (FD_ISSET(iorq->fd, rfds))
1160 					{
1161 						/* Read the data */
1162 						fns = iorq->fns;
1163 
1164 						req_size =
1165 							(iorq->length - iorq->partial_len) >
1166 							8192 ? 8192 : (iorq->length -
1167 								       iorq->partial_len);
1168 						/* never read larger chunks than 8k - chances are that it will block */
1169 						status = fns->read(iorq->fd,
1170 								   iorq->buffer + iorq->partial_len,
1171 								   req_size, iorq->offset, &result);
1172 
1173 						if ((long) result > 0)
1174 						{
1175 							iorq->partial_len += result;
1176 							iorq->offset += result;
1177 						}
1178 
1179 						logger(Protocol, Debug,
1180 						       "_rdpdr_check_fds(), %d bytes of data read",
1181 						       result);
1182 
1183 						/* only delete link if all data has been transfered */
1184 						/* or if result was 0 and status success - EOF      */
1185 						if ((iorq->partial_len == iorq->length) ||
1186 						    (result == 0))
1187 						{
1188 							logger(Protocol, Debug,
1189 							       "_rdpdr_check_fds(), AIO total %u bytes read of %u",
1190 							       iorq->partial_len, iorq->length);
1191 							rdpdr_send_completion(iorq->device,
1192 									      iorq->id, status,
1193 									      iorq->partial_len,
1194 									      iorq->buffer,
1195 									      iorq->partial_len);
1196 							iorq = rdpdr_remove_iorequest(prev, iorq);
1197 						}
1198 					}
1199 					break;
1200 				case IRP_MJ_WRITE:
1201 					if (FD_ISSET(iorq->fd, wfds))
1202 					{
1203 						/* Write data. */
1204 						fns = iorq->fns;
1205 
1206 						req_size =
1207 							(iorq->length - iorq->partial_len) >
1208 							8192 ? 8192 : (iorq->length -
1209 								       iorq->partial_len);
1210 
1211 						/* never write larger chunks than 8k - chances are that it will block */
1212 						status = fns->write(iorq->fd,
1213 								    iorq->buffer +
1214 								    iorq->partial_len, req_size,
1215 								    iorq->offset, &result);
1216 
1217 						if ((long) result > 0)
1218 						{
1219 							iorq->partial_len += result;
1220 							iorq->offset += result;
1221 						}
1222 
1223 						logger(Protocol, Debug,
1224 						       "_rdpdr_check_fds(), %d bytes of data written",
1225 						       result);
1226 
1227 						/* only delete link if all data has been transfered */
1228 						/* or we couldn't write */
1229 						if ((iorq->partial_len == iorq->length)
1230 						    || (result == 0))
1231 						{
1232 							logger(Protocol, Debug,
1233 							       "_rdpdr_check_fds(), AIO total %u bytes written of %u",
1234 							       iorq->partial_len, iorq->length);
1235 							rdpdr_send_completion(iorq->device,
1236 									      iorq->id, status,
1237 									      iorq->partial_len,
1238 									      (uint8 *) "", 1);
1239 
1240 							iorq = rdpdr_remove_iorequest(prev, iorq);
1241 						}
1242 					}
1243 					break;
1244 				case IRP_MJ_DEVICE_CONTROL:
1245 					if (serial_get_event(iorq->fd, &result))
1246 					{
1247 						buffer = (uint8 *) xrealloc((void *) buffer, 0x14);
1248 						out.data = out.p = buffer;
1249 						out.size = sizeof(buffer);
1250 						out_uint32_le(&out, result);
1251 						result = buffer_len = out.p - out.data;
1252 						status = RD_STATUS_SUCCESS;
1253 						rdpdr_send_completion(iorq->device, iorq->id,
1254 								      status, result, buffer,
1255 								      buffer_len);
1256 						xfree(buffer);
1257 						iorq = rdpdr_remove_iorequest(prev, iorq);
1258 					}
1259 
1260 					break;
1261 			}
1262 
1263 		}
1264 		prev = iorq;
1265 		if (iorq)
1266 			iorq = iorq->next;
1267 	}
1268 
1269 	/* Check notify */
1270 	iorq = g_iorequest;
1271 	prev = NULL;
1272 	while (iorq != NULL)
1273 	{
1274 		if (iorq->fd != 0)
1275 		{
1276 			switch (iorq->major)
1277 			{
1278 
1279 				case IRP_MJ_DIRECTORY_CONTROL:
1280 					if (g_rdpdr_device[iorq->device].device_type ==
1281 					    DEVICE_TYPE_DISK)
1282 					{
1283 
1284 						if (g_notify_stamp)
1285 						{
1286 							g_notify_stamp = False;
1287 							status = disk_check_notify(iorq->fd);
1288 							if (status != RD_STATUS_PENDING)
1289 							{
1290 								rdpdr_send_completion(iorq->device,
1291 										      iorq->id,
1292 										      status, 0,
1293 										      NULL, 0);
1294 								iorq = rdpdr_remove_iorequest(prev,
1295 											      iorq);
1296 							}
1297 						}
1298 					}
1299 					break;
1300 
1301 
1302 
1303 			}
1304 		}
1305 
1306 		prev = iorq;
1307 		if (iorq)
1308 			iorq = iorq->next;
1309 	}
1310 
1311 }
1312 
1313 void
rdpdr_check_fds(fd_set * rfds,fd_set * wfds,RD_BOOL timed_out)1314 rdpdr_check_fds(fd_set * rfds, fd_set * wfds, RD_BOOL timed_out)
1315 {
1316 	fd_set dummy;
1317 
1318 
1319 	FD_ZERO(&dummy);
1320 
1321 
1322 	/* fist check event queue only,
1323 	   any serial wait event must be done before read block will be sent
1324 	 */
1325 
1326 	_rdpdr_check_fds(&dummy, &dummy, False);
1327 	_rdpdr_check_fds(rfds, wfds, timed_out);
1328 }
1329 
1330 
1331 /* Abort a pending io request for a given handle and major */
1332 RD_BOOL
rdpdr_abort_io(uint32 fd,uint32 major,RD_NTSTATUS status)1333 rdpdr_abort_io(uint32 fd, uint32 major, RD_NTSTATUS status)
1334 {
1335 	uint32 result;
1336 	struct async_iorequest *iorq;
1337 	struct async_iorequest *prev;
1338 
1339 	iorq = g_iorequest;
1340 	prev = NULL;
1341 	while (iorq != NULL)
1342 	{
1343 		/* Only remove from table when major is not set, or when correct major is supplied.
1344 		   Abort read should not abort a write io request. */
1345 		if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
1346 		{
1347 			result = 0;
1348 			rdpdr_send_completion(iorq->device, iorq->id, status, result, (uint8 *) "",
1349 					      1);
1350 
1351 			iorq = rdpdr_remove_iorequest(prev, iorq);
1352 			return True;
1353 		}
1354 
1355 		prev = iorq;
1356 		iorq = iorq->next;
1357 	}
1358 
1359 	return False;
1360 }
1361