From 0a500b3554c29451708353279eefce750f4bca6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rgen=20Sigvardsson?= Date: Sat, 15 Apr 2023 18:11:19 +0200 Subject: [PATCH] scp: option to not quote paths (#803) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new flag named `LIBSSH2_FLAG_QUOTE_PATHS` has been added, to make libssh2 not quote file paths sent to the remote's scp subsystem. Some custom ssh daemons cannot handle quoted paths, and this makes this flag useful. Authored-by: Jörgen Sigvardsson --- include/libssh2.h | 1 + src/libssh2_priv.h | 5 +++-- src/scp.c | 37 +++++++++++++++++++++++++++++++------ src/session.c | 5 +++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/include/libssh2.h b/include/libssh2.h index 6bce4e26..0dd1beb8 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -372,6 +372,7 @@ typedef struct _LIBSSH2_SK_SIG_INFO { /* flags */ #define LIBSSH2_FLAG_SIGPIPE 1 #define LIBSSH2_FLAG_COMPRESS 2 +#define LIBSSH2_FLAG_QUOTE_PATHS 3 typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL; diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 01289727..428dad1c 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -578,8 +578,9 @@ struct _LIBSSH2_PUBLICKEY #define LIBSSH2_SCP_RESPONSE_BUFLEN 256 struct flags { - int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */ - int compress; /* LIBSSH2_FLAG_COMPRESS */ + int sigpipe; /* LIBSSH2_FLAG_SIGPIPE */ + int compress; /* LIBSSH2_FLAG_COMPRESS */ + int quote_paths; /* LIBSSH2_FLAG_QUOTE_PATHS */ }; struct _LIBSSH2_SESSION diff --git a/src/scp.c b/src/scp.c index 4fb81b92..6ade9102 100644 --- a/src/scp.c +++ b/src/scp.c @@ -299,9 +299,21 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, libssh2_struct_stat * sb) "scp -%sf ", sb ? "p" : ""); cmd_len = strlen((char *)session->scpRecv_command); - cmd_len += shell_quotearg(path, - &session->scpRecv_command[cmd_len], - session->scpRecv_command_len - cmd_len); + + if(!session->flag.quote_paths) { + size_t path_len; + + path_len = strlen(path); + + /* no NUL-termination neeed, so memcpy will do */ + memcpy(&session->scpRecv_command[cmd_len], path, path_len); + cmd_len += path_len; + } + else { + cmd_len += shell_quotearg(path, + &session->scpRecv_command[cmd_len], + session->scpRecv_command_len - cmd_len); + } /* the command to exec should _not_ be NUL-terminated */ session->scpRecv_command_len = cmd_len; @@ -860,9 +872,22 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, "scp -%st ", (mtime || atime) ? "p" : ""); cmd_len = strlen((char *)session->scpSend_command); - cmd_len += shell_quotearg(path, - &session->scpSend_command[cmd_len], - session->scpSend_command_len - cmd_len); + + if(!session->flag.quote_paths) { + size_t path_len; + + path_len = strlen(path); + + /* no NUL-termination neeed, so memcpy will do */ + memcpy(&session->scpSend_command[cmd_len], path, path_len); + cmd_len += path_len; + + } + else { + cmd_len += shell_quotearg(path, + &session->scpSend_command[cmd_len], + session->scpSend_command_len - cmd_len); + } /* the command to exec should _not_ be NUL-terminated */ session->scpSend_command_len = cmd_len; diff --git a/src/session.c b/src/session.c index eea239e2..35d2d68a 100644 --- a/src/session.c +++ b/src/session.c @@ -524,6 +524,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), session->api_timeout = 0; /* timeout-free API by default */ session->api_block_mode = 1; /* blocking API by default */ session->packet_read_timeout = LIBSSH2_DEFAULT_READ_TIMEOUT; + session->flag.quote_paths = 1; /* default behavior is to quote paths + for the scp subsystem */ _libssh2_debug((session, LIBSSH2_TRACE_TRANS, "New session resource allocated")); _libssh2_init_if_needed(); @@ -1409,6 +1411,9 @@ libssh2_session_flag(LIBSSH2_SESSION * session, int flag, int value) case LIBSSH2_FLAG_COMPRESS: session->flag.compress = value; break; + case LIBSSH2_FLAG_QUOTE_PATHS: + session->flag.quote_paths = value; + break; default: /* unknown flag */ return LIBSSH2_ERROR_INVAL;