keep trailing delimiter with SFTP open

pull/743/head
JacobBarthelmeh 2024-09-30 15:49:33 -06:00
parent 3cabbdb703
commit 52e4e32529
7 changed files with 118 additions and 16 deletions

View File

@ -60,6 +60,7 @@ run_test() {
run_test "sshd_exec_test.sh"
run_test "sshd_term_size_test.sh"
run_test "sshd_large_sftp_test.sh"
run_test "sshd_bad_sftp_test.sh"
#Github actions needs resolved for these test cases
#run_test "error_return.sh"

View File

@ -0,0 +1,34 @@
#!/bin/sh
# sshd local test
PWD=`pwd`
cd ../../..
TEST_SFTP_CLIENT="./examples/sftpclient/wolfsftp"
USER=`whoami`
PRIVATE_KEY="./keys/hansel-key-ecc.der"
PUBLIC_KEY="./keys/hansel-key-ecc.pub"
if [ -z "$1" ] || [ -z "$2" ]; then
echo "expecting host and port as arguments"
echo "./sshd_exec_test.sh 127.0.0.1 22222"
exit 1
fi
mkdir test-$$
mkdir test-$$/subfolder
echo "$TEST_SFTP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -g -l configure -r `pwd`/test-$$/subfolder/ -h \"$1\" -p \"$2\""
"$TEST_SFTP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -g -l configure -r `pwd`/test-$$/subfolder/ -h $1 -p $2"
RESULT=$?
if [ "$RESULT" = "0" ]; then
echo "Expecting to fail transfer to folder"
exit 1
fi
rm -rf test-$$
cd $PWD
exit 0

View File

@ -15686,6 +15686,57 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success)
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
!defined(NO_WOLFSSH_SERVER)
/* Checks if 'in' is absolute path, if not the returns the concat. of
* 'defaultPath' | 'in'. This leaves 'in' as-is and does not handle
* simplification of the path, such as removing ../
*
* Sanity checks outSz and then adjusts it for the size used
* returns WS_SUCCESS on success
*/
int wolfSSH_GetPath(const char* defaultPath, byte* in, word32 inSz,
char* out, word32* outSz)
{
word32 curSz = 0;
if (out != NULL) {
WMEMSET(out, 0, *outSz);
}
if (inSz == 0 || (!WOLFSSH_SFTP_IS_DELIM(in[0]) &&
!WOLFSSH_SFTP_IS_WINPATH(inSz, in))) {
if (defaultPath != NULL) {
curSz = (word32)WSTRLEN(defaultPath);
if (out != NULL && curSz >= *outSz) {
return WS_INVALID_PATH_E;
}
if (out != NULL) {
WSTRNCPY(out, defaultPath, *outSz);
if (out[curSz] != '/') {
out[curSz] = '/';
curSz++;
}
}
}
}
if (out != NULL) {
WMEMCPY(out + curSz, in, inSz);
}
curSz += inSz;
if (out != NULL) {
if (!WOLFSSH_SFTP_IS_DELIM(out[0])) {
WMEMMOVE(out+1, out, curSz);
out[0] = '/';
curSz++;
}
out[curSz] = 0;
}
*outSz = curSz;
return WS_SUCCESS;
}
/* cleans up absolute path
* returns size of new path on success (strlen sz) and negative values on fail*/
int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)

View File

@ -3276,10 +3276,6 @@ void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh)
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
!defined(NO_WOLFSSH_SERVER)
#define DELIM "/\\"
#define IS_DELIM(x) ((x) == '/' || (x) == '\\')
#define IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
/*
* Paths starting with a slash are absolute, rooted at "/". Any path that
* doesn't have a starting slash is assumed to be relative to the default
@ -3288,6 +3284,8 @@ void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh)
* The path "/." is stripped out. The path "/.." strips out the previous
* path value. The root path, "/", is always present.
*
* Trailing delimiters are stripped, i.e /tmp/path/ becomes /tmp/path
*
* Example: "/home/fred/frob/frizz/../../../barney/bar/baz/./././../.."
* will return "/home/barney". "/../.." will return "/". "." will return
* the default path.
@ -3319,7 +3317,8 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
inSz = (word32)WSTRLEN(in);
out[0] = '/';
curSz = 1;
if (inSz == 0 || (!IS_DELIM(in[0]) && !IS_WINPATH(inSz, in))) {
if (inSz == 0 || (!WOLFSSH_SFTP_IS_DELIM(in[0]) &&
!WOLFSSH_SFTP_IS_WINPATH(inSz, in))) {
if (defaultPath != NULL) {
curSz = (word32)WSTRLEN(defaultPath);
if (curSz >= outSz) {
@ -3330,9 +3329,9 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
}
out[curSz] = 0;
for (seg = WSTRTOK(in, DELIM, &tail);
for (seg = WSTRTOK(in, WOLFSSH_SFTP_DELIM, &tail);
seg;
seg = WSTRTOK(NULL, DELIM, &tail)) {
seg = WSTRTOK(NULL, WOLFSSH_SFTP_DELIM, &tail)) {
segSz = (word32)WSTRLEN(seg);
/* Try to match "." */

View File

@ -1974,7 +1974,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
{
WS_SFTP_FILEATRB atr;
WFD fd;
word32 sz;
word32 sz, dirSz;
char dir[WOLFSSH_MAX_FILENAME];
word32 reason;
word32 idx = 0;
@ -2010,10 +2010,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_BUFFER_E;
}
ret = GetAndCleanPath(ssh->sftpDefaultPath, data + idx, sz,
dir, sizeof(dir));
if (ret < 0) {
return ret;
dirSz = sizeof(dir);
if (wolfSSH_GetPath(ssh->sftpDefaultPath, data + idx, sz, dir, &dirSz)
!= WS_SUCCESS) {
WLOG(WS_LOG_SFTP, "Creating path for file to open failed");
return WS_FATAL_ERROR;
}
idx += sz;
@ -2128,7 +2129,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
{
/* WS_SFTP_FILEATRB atr;*/
HANDLE fileHandle;
word32 sz;
word32 sz, dirSz;
char dir[WOLFSSH_MAX_FILENAME];
word32 reason;
word32 idx = 0;
@ -2165,9 +2166,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_BUFFER_E;
}
if (GetAndCleanPath(ssh->sftpDefaultPath,
data + idx, sz, dir, sizeof(dir)) < 0) {
return WS_BUFFER_E;
dirSz = sizeof(dir);
if (wolfSSH_GetPath(ssh->sftpDefaultPath, data + idx, sz, dir, &dirSz)
!= WS_SUCCESS) {
WLOG(WS_LOG_SFTP, "Creating path for file to open failed");
return WS_FATAL_ERROR;
}
idx += sz;

View File

@ -620,6 +620,12 @@ typedef struct HandshakeInfo {
} privKey;
} HandshakeInfo;
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
!defined(NO_WOLFSSH_SERVER)
WOLFSSH_LOCAL int wolfSSH_GetPath(const char* defaultPath, byte* in,
word32 inSz, char* out, word32* outSz);
#endif
#ifdef WOLFSSH_SFTP
#define WOLFSSH_MAX_SFTPOFST 3

View File

@ -575,6 +575,14 @@ extern "C" {
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
#endif
#ifndef WOLFSSH_SFTP_DELIM
/* Delimiter's used between two SFTP peers should be the same regardless of
* operating system. WS_DELIM defined elsewhere is OS specific delimiter. */
#define WOLFSSH_SFTP_DELIM "/\\"
#define WOLFSSH_SFTP_IS_DELIM(x) ((x) == '/' || (x) == '\\')
#define WOLFSSH_SFTP_IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
#endif
#if (defined(WOLFSSH_SFTP) || \
defined(WOLFSSH_SCP) || defined(WOLFSSH_SSHD)) && \
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)