From 6cf5f0e340370ecdc80e300a2622f47fe04c5682 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Sat, 9 Sep 2023 08:49:43 +0200 Subject: [PATCH] sftp: Cap maximum SFTP write The curl does not do any (or enough) chunking when writing large files using the sftp_write() function which causes some servers to choke [1]. The simplest solution is to limit the SFTP packet size according the SFTP specification recommendation which is 32768 B and not write more. This means the function will not write the whole amount of data it was asked to write and the calling applications are required to handle the return values correctly. More complicated solution would be to send several SFTP packet from the single sftp_write() function by iterating over the all data passed. The next improvement in the long term should be respecting the value reported by the server in the limits@openssh.com extension, which specifies the maximum packet size and reads/writes explicitly (if supported). [1] https://github.com/curl/curl/pull/11804 Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- include/libssh/sftp.h | 4 ++++ src/sftp.c | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/libssh/sftp.h b/include/libssh/sftp.h index e210a1be..4b4f8481 100644 --- a/include/libssh/sftp.h +++ b/include/libssh/sftp.h @@ -550,6 +550,10 @@ LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_ /** * @brief Write to a file using an opened sftp file handle. * + * The maximum size of the SFTP packet payload is 32768 bytes so the count + * parameter is capped at this value. This is low-level function so it does not + * try to send more than this amount of data. + * * @param file Open sftp file handle to write to. * * @param buf Pointer to buffer to write data. diff --git a/src/sftp.c b/src/sftp.c index d95af819..c1f29449 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -2211,6 +2211,17 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) { id = sftp_get_new_id(file->sftp); + + /* limit the writes to the maximum specified in Section 3 of + * https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02 + * + * FIXME: This value should be adjusted to the value from the + * limits@openssh.com extension if supported + * TODO: We should iterate over the blocks rather than writing less than + * requested to provide less surprises to the calling applications. + */ + count = count > 32768 ? 32768 : count; + rc = ssh_buffer_pack(buffer, "dSqdP", id,