From ad13956b126a764e14b0016d89feb8407b1fa938 Mon Sep 17 00:00:00 2001
From: Koichiro IWAO
Date: Wed, 15 Sep 2021 18:20:15 +0900
Subject: [PATCH 1/2] clipboard file: Implement MS-RDPECLIP 3.1.5.4.7
compliance
If the requested file data could not be retrieved or the sender received
an unsuccessful Format List Response PDU (section 3.1.5.2.4), then the
clipHeader field MUST contain the CB_RESPONSE_FAIL (0x0002) flag and the
requestedFileContentsData field MUST contain no data (zero-length).
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeclip/5d3991e9-440d-4e4d-8b8d-391c324c4007
Fixes #1997.
---
sesman/chansrv/clipboard_file.c | 48 +++++++++++++++++++++++++++++++--
sesman/chansrv/clipboard_file.h | 1 +
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c
index c317da79..3af75c58 100644
--- a/sesman/chansrv/clipboard_file.c
+++ b/sesman/chansrv/clipboard_file.c
@@ -82,6 +82,37 @@ timeval2wintime(struct timeval *tv)
}
#endif
+/***
+ * See MS-RDPECLIP 3.1.5.4.7
+ *
+ * Sends a failure response to a CLIPRDR_FILECONTENTS_REQUEST
+ * @param streamId Stream ID from CLIPRDR_FILECONTENTS_REQUEST
+ * @return 0 for success
+ */
+
+static int
+clipboard_send_filecontents_response_fail(int streamId)
+{
+ LOG_DEVEL(LOG_LEVEL_TRACE, "clipboardn_send_filecontents_response_fail:");
+
+ struct stream *s;
+ int size;
+ int rv;
+
+ make_stream(s);
+ init_stream(s, 64);
+
+ out_uint16_le(s, CB_FILECONTENTS_RESPONSE);
+ out_uint16_le(s, CB_RESPONSE_FAIL);
+ out_uint32_le(s, 4);
+ out_uint32_le(s, streamId);
+ s_mark_end(s);
+ size = (int)(s->end - s->data);
+ rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
+ free_stream(s);
+ return rv;
+}
+
/*****************************************************************************/
/* this will replace %20 or any hex with the space or correct char
* returns error */
@@ -318,12 +349,20 @@ clipboard_send_file_size(int streamId, int lindex)
if (g_files_list == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_size: error g_files_list is nil");
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
cfi = (struct cb_file_info *)list_get_item(g_files_list, lindex);
if (cfi == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_size: error cfi is nil");
+ clipboard_send_filecontents_response_fail(streamId);
+ return 1;
+ }
+ if (cfi->size < 0)
+ {
+ LOG(LOG_LEVEL_ERROR, "clipboard_send_file_size: failed to get file size");
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
file_size = cfi->size;
@@ -397,12 +436,14 @@ clipboard_send_file_data(int streamId, int lindex,
if (g_files_list == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: error g_files_list is nil");
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
cfi = (struct cb_file_info *)list_get_item(g_files_list, lindex);
if (cfi == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: error cfi is nil");
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_send_file_data: streamId %d lindex %d "
@@ -412,8 +453,9 @@ clipboard_send_file_data(int streamId, int lindex,
fd = g_file_open_ex(full_fn, 1, 0, 0, 0);
if (fd == -1)
{
- LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: file open [%s] failed",
- full_fn);
+ LOG(LOG_LEVEL_ERROR, "clipboard_send_file_data: file open [%s] failed: %s",
+ full_fn, g_get_strerror());
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
if (g_file_seek(fd, nPositionLow) < 0)
@@ -421,6 +463,7 @@ clipboard_send_file_data(int streamId, int lindex,
LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error "
"in file: %s", full_fn);
g_file_close(fd);
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
make_stream(s);
@@ -432,6 +475,7 @@ clipboard_send_file_data(int streamId, int lindex,
cbRequested, size);
free_stream(s);
g_file_close(fd);
+ clipboard_send_filecontents_response_fail(streamId);
return 1;
}
out_uint16_le(s, CB_FILECONTENTS_RESPONSE); /* 9 */
diff --git a/sesman/chansrv/clipboard_file.h b/sesman/chansrv/clipboard_file.h
index 16377b0e..37eaee5c 100644
--- a/sesman/chansrv/clipboard_file.h
+++ b/sesman/chansrv/clipboard_file.h
@@ -35,6 +35,7 @@ clipboard_c2s_in_files(struct stream *s, char *file_list);
int
clipboard_request_file_size(int stream_id, int lindex);
+
int
clipboard_request_file_data(int stream_id, int lindex, int offset,
int request_bytes);
From eb848747d2193b0390ad1699f614152a763a1736 Mon Sep 17 00:00:00 2001
From: Koichiro IWAO
Date: Tue, 21 Sep 2021 18:19:47 +0900
Subject: [PATCH 2/2] clipboard file: adjust log level and add some detailed
info
---
sesman/chansrv/clipboard_file.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c
index 3af75c58..4834d9c4 100644
--- a/sesman/chansrv/clipboard_file.c
+++ b/sesman/chansrv/clipboard_file.c
@@ -361,7 +361,8 @@ clipboard_send_file_size(int streamId, int lindex)
}
if (cfi->size < 0)
{
- LOG(LOG_LEVEL_ERROR, "clipboard_send_file_size: failed to get file size");
+ LOG(LOG_LEVEL_ERROR, "clipboard_send_file_size: error cfi->size is negative"
+ "value [%d]", cfi->size);
clipboard_send_filecontents_response_fail(streamId);
return 1;
}
@@ -460,8 +461,8 @@ clipboard_send_file_data(int streamId, int lindex,
}
if (g_file_seek(fd, nPositionLow) < 0)
{
- LOG_DEVEL(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error "
- "in file: %s", full_fn);
+ LOG(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error in file [%s]: %s",
+ full_fn, g_get_strerror());
g_file_close(fd);
clipboard_send_filecontents_response_fail(streamId);
return 1;