mirror of https://github.com/wolfSSL/wolfssh.git
keep trailing delimiter with SFTP open
parent
3cabbdb703
commit
52e4e32529
|
@ -60,6 +60,7 @@ run_test() {
|
||||||
run_test "sshd_exec_test.sh"
|
run_test "sshd_exec_test.sh"
|
||||||
run_test "sshd_term_size_test.sh"
|
run_test "sshd_term_size_test.sh"
|
||||||
run_test "sshd_large_sftp_test.sh"
|
run_test "sshd_large_sftp_test.sh"
|
||||||
|
run_test "sshd_bad_sftp_test.sh"
|
||||||
|
|
||||||
#Github actions needs resolved for these test cases
|
#Github actions needs resolved for these test cases
|
||||||
#run_test "error_return.sh"
|
#run_test "error_return.sh"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -15686,6 +15686,57 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success)
|
||||||
|
|
||||||
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
||||||
!defined(NO_WOLFSSH_SERVER)
|
!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
|
/* cleans up absolute path
|
||||||
* returns size of new path on success (strlen sz) and negative values on fail*/
|
* returns size of new path on success (strlen sz) and negative values on fail*/
|
||||||
int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
|
int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
|
||||||
|
|
13
src/ssh.c
13
src/ssh.c
|
@ -3276,10 +3276,6 @@ void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh)
|
||||||
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
||||||
!defined(NO_WOLFSSH_SERVER)
|
!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
|
* 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
|
* 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
|
* The path "/." is stripped out. The path "/.." strips out the previous
|
||||||
* path value. The root path, "/", is always present.
|
* 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/./././../.."
|
* Example: "/home/fred/frob/frizz/../../../barney/bar/baz/./././../.."
|
||||||
* will return "/home/barney". "/../.." will return "/". "." will return
|
* will return "/home/barney". "/../.." will return "/". "." will return
|
||||||
* the default path.
|
* the default path.
|
||||||
|
@ -3319,7 +3317,8 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
|
||||||
inSz = (word32)WSTRLEN(in);
|
inSz = (word32)WSTRLEN(in);
|
||||||
out[0] = '/';
|
out[0] = '/';
|
||||||
curSz = 1;
|
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) {
|
if (defaultPath != NULL) {
|
||||||
curSz = (word32)WSTRLEN(defaultPath);
|
curSz = (word32)WSTRLEN(defaultPath);
|
||||||
if (curSz >= outSz) {
|
if (curSz >= outSz) {
|
||||||
|
@ -3330,9 +3329,9 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
|
||||||
}
|
}
|
||||||
out[curSz] = 0;
|
out[curSz] = 0;
|
||||||
|
|
||||||
for (seg = WSTRTOK(in, DELIM, &tail);
|
for (seg = WSTRTOK(in, WOLFSSH_SFTP_DELIM, &tail);
|
||||||
seg;
|
seg;
|
||||||
seg = WSTRTOK(NULL, DELIM, &tail)) {
|
seg = WSTRTOK(NULL, WOLFSSH_SFTP_DELIM, &tail)) {
|
||||||
segSz = (word32)WSTRLEN(seg);
|
segSz = (word32)WSTRLEN(seg);
|
||||||
|
|
||||||
/* Try to match "." */
|
/* Try to match "." */
|
||||||
|
|
|
@ -1974,7 +1974,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
||||||
{
|
{
|
||||||
WS_SFTP_FILEATRB atr;
|
WS_SFTP_FILEATRB atr;
|
||||||
WFD fd;
|
WFD fd;
|
||||||
word32 sz;
|
word32 sz, dirSz;
|
||||||
char dir[WOLFSSH_MAX_FILENAME];
|
char dir[WOLFSSH_MAX_FILENAME];
|
||||||
word32 reason;
|
word32 reason;
|
||||||
word32 idx = 0;
|
word32 idx = 0;
|
||||||
|
@ -2010,10 +2010,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
||||||
return WS_BUFFER_E;
|
return WS_BUFFER_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GetAndCleanPath(ssh->sftpDefaultPath, data + idx, sz,
|
dirSz = sizeof(dir);
|
||||||
dir, sizeof(dir));
|
if (wolfSSH_GetPath(ssh->sftpDefaultPath, data + idx, sz, dir, &dirSz)
|
||||||
if (ret < 0) {
|
!= WS_SUCCESS) {
|
||||||
return ret;
|
WLOG(WS_LOG_SFTP, "Creating path for file to open failed");
|
||||||
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
idx += sz;
|
idx += sz;
|
||||||
|
|
||||||
|
@ -2128,7 +2129,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
||||||
{
|
{
|
||||||
/* WS_SFTP_FILEATRB atr;*/
|
/* WS_SFTP_FILEATRB atr;*/
|
||||||
HANDLE fileHandle;
|
HANDLE fileHandle;
|
||||||
word32 sz;
|
word32 sz, dirSz;
|
||||||
char dir[WOLFSSH_MAX_FILENAME];
|
char dir[WOLFSSH_MAX_FILENAME];
|
||||||
word32 reason;
|
word32 reason;
|
||||||
word32 idx = 0;
|
word32 idx = 0;
|
||||||
|
@ -2165,9 +2166,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
||||||
return WS_BUFFER_E;
|
return WS_BUFFER_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetAndCleanPath(ssh->sftpDefaultPath,
|
dirSz = sizeof(dir);
|
||||||
data + idx, sz, dir, sizeof(dir)) < 0) {
|
if (wolfSSH_GetPath(ssh->sftpDefaultPath, data + idx, sz, dir, &dirSz)
|
||||||
return WS_BUFFER_E;
|
!= WS_SUCCESS) {
|
||||||
|
WLOG(WS_LOG_SFTP, "Creating path for file to open failed");
|
||||||
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
idx += sz;
|
idx += sz;
|
||||||
|
|
||||||
|
|
|
@ -620,6 +620,12 @@ typedef struct HandshakeInfo {
|
||||||
} privKey;
|
} privKey;
|
||||||
} HandshakeInfo;
|
} 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
|
#ifdef WOLFSSH_SFTP
|
||||||
#define WOLFSSH_MAX_SFTPOFST 3
|
#define WOLFSSH_MAX_SFTPOFST 3
|
||||||
|
|
||||||
|
|
|
@ -575,6 +575,14 @@ extern "C" {
|
||||||
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
|
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
|
||||||
#endif
|
#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) || \
|
#if (defined(WOLFSSH_SFTP) || \
|
||||||
defined(WOLFSSH_SCP) || defined(WOLFSSH_SSHD)) && \
|
defined(WOLFSSH_SCP) || defined(WOLFSSH_SSHD)) && \
|
||||||
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
|
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
|
||||||
|
|
Loading…
Reference in New Issue