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 = ¶llel_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