From a3d429b4f7bc5d06236c48df7e9b1f770514f7c9 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Tue, 3 Mar 2020 10:02:32 +0000 Subject: [PATCH] Minor fixes to drive redirection --- common/ms-erref.h | 3 +- sesman/chansrv/chansrv_fuse.c | 54 ++++++++++++++------- sesman/chansrv/chansrv_fuse.h | 1 + sesman/chansrv/chansrv_xfs.c | 4 +- sesman/chansrv/devredir.c | 89 ++++++++++++++++++++--------------- sesman/chansrv/devredir.h | 9 ++-- 6 files changed, 100 insertions(+), 60 deletions(-) diff --git a/common/ms-erref.h b/common/ms-erref.h index 3b1b75e5..394766a1 100644 --- a/common/ms-erref.h +++ b/common/ms-erref.h @@ -36,7 +36,8 @@ enum NTSTATUS STATUS_ACCESS_DENIED = 0xc0000022, STATUS_OBJECT_NAME_INVALID = 0xc0000033, STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034, - STATUS_SHARING_VIOLATION = 0xc0000043 + STATUS_SHARING_VIOLATION = 0xc0000043, + STATUS_NOT_SUPPORTED = 0xc00000bb }; #endif /* MS_ERREF_H */ diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index b57cc662..178d1ded 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -78,6 +78,7 @@ void xfuse_devredir_cb_open_file(struct state_open *fip, tui32 DeviceId, tui32 FileId) {} void xfuse_devredir_cb_read_file(struct state_read *fip, + enum NTSTATUS IoStatus, const char *buf, size_t length) {} void xfuse_devredir_cb_write_file( @@ -1313,9 +1314,18 @@ void xfuse_devredir_cb_open_file(struct state_open *fip, } void xfuse_devredir_cb_read_file(struct state_read *fip, + enum NTSTATUS IoStatus, const char *buf, size_t length) { - fuse_reply_buf(fip->req, buf, length); + if (IoStatus != STATUS_SUCCESS) + { + log_error("Read NTSTATUS is %d", (int) IoStatus); + fuse_reply_err(fip->req, EIO); + } + else + { + fuse_reply_buf(fip->req, buf, length); + } free(fip); } @@ -1679,7 +1689,7 @@ static void xfuse_cb_unlink(fuse_req_t req, fuse_ino_t parent, //XFUSE_HANDLE *fh; log_debug("LK_TODO: this is still a TODO"); - fuse_reply_err(req, EINVAL); + fuse_reply_err(req, EROFS); } else { @@ -1744,26 +1754,26 @@ static void xfuse_cb_rename(fuse_req_t req, else if (!(new_parent_xinode = xfs_get(g_xfs, new_parent))) { log_error("inode %ld is not valid", new_parent); - fuse_reply_err(req, EINVAL); + fuse_reply_err(req, ENOENT); } else if (!xfs_check_move_entry(g_xfs, old_xinode->inum, new_parent, new_name)) { + /* Catchall -see rename(2). Fix when logging is improved */ fuse_reply_err(req, EINVAL); } else if (new_parent_xinode->device_id != old_xinode->device_id) { - log_error("rename across file systems not supported"); - fuse_reply_err(req, EINVAL); + fuse_reply_err(req, EXDEV); } else if (old_xinode->device_id == 0) { /* specified file is a local resource */ log_debug("LK_TODO: this is still a TODO"); - fuse_reply_err(req, EINVAL); + fuse_reply_err(req, EROFS); } else @@ -1853,20 +1863,25 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent, } /* is parent inode valid? */ - if (parent == FUSE_ROOT_ID || - (xinode = xfs_get(g_xfs, parent)) == NULL || - (xinode->mode & S_IFDIR) == 0) + if (parent == FUSE_ROOT_ID) + { + fuse_reply_err(req, EROFS); + } + else if ((xinode = xfs_get(g_xfs, parent)) == NULL) { - log_error("inode %ld is not valid", parent); fuse_reply_err(req, ENOENT); } + else if ((xinode->mode & S_IFDIR) == 0) + { + fuse_reply_err(req, ENOTDIR); + } else if (xinode->device_id == 0) { /* specified file is a local resource */ //XFUSE_HANDLE *fh; log_debug("LK_TODO: this is still a TODO"); - fuse_reply_err(req, EINVAL); + fuse_reply_err(req, EROFS); } else { @@ -1948,10 +1963,17 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino, else if (xinode->device_id == 0) { /* specified file is a local resource */ - XFUSE_HANDLE *fh = g_new0(XFUSE_HANDLE, 1); - fh->is_loc_resource = 1; - fi->fh = (tintptr) fh; - fuse_reply_open(req, fi); + if ((fi->flags & O_ACCMODE) != O_RDONLY) + { + fuse_reply_err(req, EROFS); + } + else + { + XFUSE_HANDLE *fh = g_new0(XFUSE_HANDLE, 1); + fh->is_loc_resource = 1; + fi->fh = (tintptr) fh; + fuse_reply_open(req, fi); + } } else { @@ -2153,7 +2175,7 @@ static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf, { /* target file is in .clipboard dir */ log_debug("THIS IS STILL A TODO!"); - fuse_reply_err(req, EINVAL); + fuse_reply_err(req, EROFS); } else { diff --git a/sesman/chansrv/chansrv_fuse.h b/sesman/chansrv/chansrv_fuse.h index a692dcdd..abd68343 100644 --- a/sesman/chansrv/chansrv_fuse.h +++ b/sesman/chansrv/chansrv_fuse.h @@ -98,6 +98,7 @@ void xfuse_devredir_cb_open_file(struct state_open *fip, tui32 DeviceId, tui32 FileId); void xfuse_devredir_cb_read_file(struct state_read *fip, + enum NTSTATUS IoStatus, const char *buf, size_t length); void xfuse_devredir_cb_write_file( struct state_write *fip, diff --git a/sesman/chansrv/chansrv_xfs.c b/sesman/chansrv/chansrv_xfs.c index feff7e2b..a5f009d2 100644 --- a/sesman/chansrv/chansrv_xfs.c +++ b/sesman/chansrv/chansrv_xfs.c @@ -565,7 +565,7 @@ xfs_get_full_path(struct xfs_fs *xfs, fuse_ino_t inum) */ size_t len = 0; XFS_INODE_ALL *p; - for (p = xino ; p->pub.inum != FUSE_ROOT_ID ; p = p->parent) + for (p = xino ; p && p->pub.inum != FUSE_ROOT_ID ; p = p->parent) { len += strlen(p->pub.name); ++len; /* Allow for '/' prefix */ @@ -578,7 +578,7 @@ xfs_get_full_path(struct xfs_fs *xfs, fuse_ino_t inum) char *end = result + len; *end = '\0'; - for (p = xino ; p->pub.inum != FUSE_ROOT_ID ; p = p->parent) + for (p = xino ; p && p->pub.inum != FUSE_ROOT_ID ; p = p->parent) { len = strlen(p->pub.name); end -= (len + 1); diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index 6455746b..806d9c06 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -560,7 +560,8 @@ devredir_send_server_user_logged_on(void) } static void -devredir_send_server_device_announce_resp(tui32 device_id) +devredir_send_server_device_announce_resp(tui32 device_id, + enum NTSTATUS result_code) { struct stream *s; int bytes; @@ -571,7 +572,7 @@ devredir_send_server_device_announce_resp(tui32 device_id) xstream_wr_u16_le(s, RDPDR_CTYP_CORE); xstream_wr_u16_le(s, PAKID_CORE_DEVICE_REPLY); xstream_wr_u32_le(s, device_id); - xstream_wr_u32_le(s, 0); /* ResultCode */ + xstream_wr_u32_le(s, (tui32)result_code); /* send to client */ bytes = xstream_len(s); @@ -811,6 +812,7 @@ devredir_proc_client_devlist_announce_req(struct stream *s) tui32 device_type; tui32 device_data_len; char preferred_dos_name[9]; + enum NTSTATUS response_status; /* get number of devices being announced */ xstream_rd_u32_le(s, device_count); @@ -821,19 +823,20 @@ devredir_proc_client_devlist_announce_req(struct stream *s) { xstream_rd_u32_le(s, device_type); xstream_rd_u32_le(s, g_device_id); + /* get preferred DOS name + * DOS names that are 8 chars long are not NULL terminated */ + for (j = 0; j < 8; j++) + { + preferred_dos_name[j] = *s->p++; + } + preferred_dos_name[8] = 0; + + /* Assume this device isn't supported by us */ + response_status = STATUS_NOT_SUPPORTED; switch (device_type) { case RDPDR_DTYP_FILESYSTEM: - /* get preferred DOS name */ - for (j = 0; j < 8; j++) - { - preferred_dos_name[j] = *s->p++; - } - - /* DOS names that are 8 chars long are not NULL terminated */ - preferred_dos_name[8] = 0; - /* get device data len */ xstream_rd_u32_le(s, device_data_len); if (device_data_len) @@ -847,7 +850,7 @@ devredir_proc_client_devlist_announce_req(struct stream *s) preferred_dos_name, device_data_len, g_full_name_for_filesystem); - devredir_send_server_device_announce_resp(g_device_id); + response_status = STATUS_SUCCESS; /* create share directory in xrdp file system; */ /* think of this as the mount point for this share */ @@ -855,31 +858,44 @@ devredir_proc_client_devlist_announce_req(struct stream *s) break; case RDPDR_DTYP_SMARTCARD: - /* get preferred DOS name */ - for (j = 0; j < 8; j++) - { - preferred_dos_name[j] = *s->p++; - } - - /* DOS names that are 8 chars long are not NULL terminated */ - preferred_dos_name[8] = 0; - /* for smart cards, device data len always 0 */ log_debug("device_type=SMARTCARD device_id=0x%x dosname=%s", g_device_id, preferred_dos_name); - devredir_send_server_device_announce_resp(g_device_id); + response_status = STATUS_SUCCESS; + scard_device_announce(g_device_id); break; - /* we don't yet support these devices */ case RDPDR_DTYP_SERIAL: + log_debug( + "device_type=SERIAL device_id=0x%x dosname=%s", + g_device_id, preferred_dos_name); + break; + case RDPDR_DTYP_PARALLEL: + log_debug( + "device_type=PARALLEL device_id=0x%x dosname=%s", + g_device_id, preferred_dos_name); + break; + case RDPDR_DTYP_PRINT: - log_debug("unsupported dev: 0x%x", device_type); + log_debug( + "device_type=PRINT device_id=0x%x dosname=%s", + g_device_id, preferred_dos_name); + break; + + default: + log_debug( + "device_type=UNKNOWN device_id=0x%x dosname=%s", + g_device_id, preferred_dos_name); break; } + + /* Tell the client wheth or not we're supporting this one */ + devredir_send_server_device_announce_resp(g_device_id, + response_status); } } @@ -993,6 +1009,7 @@ devredir_proc_device_iocompletion(struct stream *s) case CID_READ: xstream_rd_u32_le(s, Length); xfuse_devredir_cb_read_file((struct state_read *) irp->fuse_info, + IoStatus, s->p, Length); devredir_irp_delete(irp); break; @@ -1511,10 +1528,10 @@ devredir_rmdir_or_file(struct state_remove *fusep, tui32 device_id, /** * Read data from previously opened file * - * @return 0 on success, -1 on failure + * Errors are reported via xfuse_devredir_cb_read_file() *****************************************************************************/ -int +void devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId, tui32 Length, tui64 Offset) { @@ -1522,7 +1539,6 @@ devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId, IRP *irp; IRP *new_irp; int bytes; - int rval = -1; xstream_new(s, 1024); @@ -1530,14 +1546,14 @@ devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId, if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL) { log_error("no IRP found with FileId = %d", FileId); - xfuse_devredir_cb_read_file(fusep, NULL, 0); + xfuse_devredir_cb_read_file(fusep, STATUS_UNSUCCESSFUL, NULL, 0); xstream_free(s); } /* create a new IRP for this request */ else if ((new_irp = devredir_irp_new()) == NULL) { /* system out of memory */ - xfuse_devredir_cb_read_file(fusep, NULL, 0); + xfuse_devredir_cb_read_file(fusep, STATUS_UNSUCCESSFUL, NULL, 0); xstream_free(s); } else @@ -1563,13 +1579,16 @@ devredir_file_read(struct state_read *fusep, tui32 DeviceId, tui32 FileId, bytes = xstream_len(s); send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); - rval = 0; } - - return rval; } -int +/** + * Read data from previously opened file + * + * Errors are reported via xfuse_devredir_cb_write_file() + *****************************************************************************/ + +void devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId, const char *buf, int Length, tui64 Offset) { @@ -1577,7 +1596,6 @@ devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId, IRP *irp; IRP *new_irp; int bytes; - int rval = -1; log_debug("DeviceId=%d FileId=%d Length=%d Offset=%lld", DeviceId, FileId, Length, (long long)Offset); @@ -1625,10 +1643,7 @@ devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId, bytes = xstream_len(s); send_channel_data(g_rdpdr_chan_id, s->data, bytes); xstream_free(s); - rval = 0; } - - return rval; } diff --git a/sesman/chansrv/devredir.h b/sesman/chansrv/devredir.h index 04483753..7ad13745 100644 --- a/sesman/chansrv/devredir.h +++ b/sesman/chansrv/devredir.h @@ -78,12 +78,13 @@ int devredir_file_open(struct state_open *fusep, tui32 device_id, int devredir_file_close(struct state_close *fusep, tui32 device_id, tui32 file_id); -int devredir_file_read(struct state_read *fusep, tui32 device_id, tui32 FileId, - tui32 Length, tui64 Offset); +void +devredir_file_read(struct state_read *fusep, tui32 device_id, tui32 FileId, + tui32 Length, tui64 Offset); -int +void devredir_file_write(struct state_write *fusep, tui32 DeviceId, tui32 FileId, - const char *buf, int Length, tui64 Offset); + const char *buf, int Length, tui64 Offset); int devredir_file_rename( struct state_rename *fusep, tui32 device_id,