Skip to content

Commit d3a8ec6

Browse files
authored
Merge pull request #743 from JacobBarthelmeh/sftp
keep trailing delimiter with SFTP open
2 parents fe25b4e + 6037d0b commit d3a8ec6

7 files changed

Lines changed: 127 additions & 16 deletions

File tree

apps/wolfsshd/test/run_all_sshd_tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ run_test() {
6060
run_test "sshd_exec_test.sh"
6161
run_test "sshd_term_size_test.sh"
6262
run_test "sshd_large_sftp_test.sh"
63+
run_test "sshd_bad_sftp_test.sh"
6364

6465
#Github actions needs resolved for these test cases
6566
#run_test "error_return.sh"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/sh
2+
3+
# sshd local test
4+
5+
PWD=`pwd`
6+
cd ../../..
7+
8+
TEST_SFTP_CLIENT="./examples/sftpclient/wolfsftp"
9+
USER=`whoami`
10+
PRIVATE_KEY="./keys/hansel-key-ecc.der"
11+
PUBLIC_KEY="./keys/hansel-key-ecc.pub"
12+
13+
if [ -z "$1" ] || [ -z "$2" ]; then
14+
echo "expecting host and port as arguments"
15+
echo "./sshd_exec_test.sh 127.0.0.1 22222"
16+
exit 1
17+
fi
18+
19+
mkdir test-$$
20+
mkdir test-$$/subfolder
21+
22+
echo "$TEST_SFTP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -g -l configure -r `pwd`/test-$$/subfolder/ -h \"$1\" -p \"$2\""
23+
"$TEST_SFTP_CLIENT -u $USER -i $PRIVATE_KEY -j $PUBLIC_KEY -g -l configure -r `pwd`/test-$$/subfolder/ -h $1 -p $2"
24+
25+
RESULT=$?
26+
if [ "$RESULT" = "0" ]; then
27+
echo "Expecting to fail transfer to folder"
28+
exit 1
29+
fi
30+
rm -rf test-$$
31+
32+
cd $PWD
33+
exit 0
34+

src/internal.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15691,6 +15691,66 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success)
1569115691

1569215692
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
1569315693
!defined(NO_WOLFSSH_SERVER)
15694+
/* Checks if 'in' is absolute path, if not the returns the concat. of
15695+
* 'defaultPath' | 'in'. This leaves 'in' as-is and does not handle
15696+
* simplification of the path, such as removing ../
15697+
*
15698+
* Sanity checks outSz and then adjusts it for the size used
15699+
* returns WS_SUCCESS on success
15700+
*/
15701+
int wolfSSH_GetPath(const char* defaultPath, byte* in, word32 inSz,
15702+
char* out, word32* outSz)
15703+
{
15704+
word32 curSz = 0;
15705+
15706+
if (out != NULL) {
15707+
WMEMSET(out, 0, *outSz);
15708+
}
15709+
15710+
if (inSz == 0 || (!WOLFSSH_SFTP_IS_DELIM(in[0]) &&
15711+
!WOLFSSH_SFTP_IS_WINPATH(inSz, in))) {
15712+
if (defaultPath != NULL) {
15713+
curSz = (word32)WSTRLEN(defaultPath);
15714+
if (out != NULL && curSz >= *outSz) {
15715+
return WS_INVALID_PATH_E;
15716+
}
15717+
if (out != NULL) {
15718+
WSTRNCPY(out, defaultPath, *outSz);
15719+
if (out[curSz] != '/') {
15720+
out[curSz] = '/';
15721+
curSz++;
15722+
}
15723+
}
15724+
}
15725+
}
15726+
15727+
if (out != NULL) {
15728+
if (curSz + inSz < *outSz) {
15729+
WMEMCPY(out + curSz, in, inSz);
15730+
}
15731+
}
15732+
curSz += inSz;
15733+
if (out != NULL) {
15734+
if (!WOLFSSH_SFTP_IS_DELIM(out[0])) {
15735+
if (curSz + 1 < *outSz) {
15736+
WMEMMOVE(out+1, out, curSz);
15737+
out[0] = '/';
15738+
}
15739+
curSz++;
15740+
}
15741+
if (curSz < *outSz) {
15742+
out[curSz] = 0;
15743+
}
15744+
else {
15745+
return WS_BUFFER_E;
15746+
}
15747+
}
15748+
*outSz = curSz;
15749+
15750+
return WS_SUCCESS;
15751+
}
15752+
15753+
1569415754
/* cleans up absolute path
1569515755
* returns size of new path on success (strlen sz) and negative values on fail*/
1569615756
int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)

src/ssh.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3276,10 +3276,6 @@ void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh)
32763276
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
32773277
!defined(NO_WOLFSSH_SERVER)
32783278

3279-
#define DELIM "/\\"
3280-
#define IS_DELIM(x) ((x) == '/' || (x) == '\\')
3281-
#define IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
3282-
32833279
/*
32843280
* Paths starting with a slash are absolute, rooted at "/". Any path that
32853281
* doesn't have a starting slash is assumed to be relative to the default
@@ -3288,6 +3284,8 @@ void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh)
32883284
* The path "/." is stripped out. The path "/.." strips out the previous
32893285
* path value. The root path, "/", is always present.
32903286
*
3287+
* Trailing delimiters are stripped, i.e /tmp/path/ becomes /tmp/path
3288+
*
32913289
* Example: "/home/fred/frob/frizz/../../../barney/bar/baz/./././../.."
32923290
* will return "/home/barney". "/../.." will return "/". "." will return
32933291
* the default path.
@@ -3319,7 +3317,8 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
33193317
inSz = (word32)WSTRLEN(in);
33203318
out[0] = '/';
33213319
curSz = 1;
3322-
if (inSz == 0 || (!IS_DELIM(in[0]) && !IS_WINPATH(inSz, in))) {
3320+
if (inSz == 0 || (!WOLFSSH_SFTP_IS_DELIM(in[0]) &&
3321+
!WOLFSSH_SFTP_IS_WINPATH(inSz, in))) {
33233322
if (defaultPath != NULL) {
33243323
curSz = (word32)WSTRLEN(defaultPath);
33253324
if (curSz >= outSz) {
@@ -3330,9 +3329,9 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
33303329
}
33313330
out[curSz] = 0;
33323331

3333-
for (seg = WSTRTOK(in, DELIM, &tail);
3332+
for (seg = WSTRTOK(in, WOLFSSH_SFTP_DELIM, &tail);
33343333
seg;
3335-
seg = WSTRTOK(NULL, DELIM, &tail)) {
3334+
seg = WSTRTOK(NULL, WOLFSSH_SFTP_DELIM, &tail)) {
33363335
segSz = (word32)WSTRLEN(seg);
33373336

33383337
/* Try to match "." */

src/wolfsftp.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
19741974
{
19751975
WS_SFTP_FILEATRB atr;
19761976
WFD fd;
1977-
word32 sz;
1977+
word32 sz, dirSz;
19781978
char dir[WOLFSSH_MAX_FILENAME];
19791979
word32 reason;
19801980
word32 idx = 0;
@@ -2010,10 +2010,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
20102010
return WS_BUFFER_E;
20112011
}
20122012

2013-
ret = GetAndCleanPath(ssh->sftpDefaultPath, data + idx, sz,
2014-
dir, sizeof(dir));
2015-
if (ret < 0) {
2016-
return ret;
2013+
dirSz = sizeof(dir);
2014+
if (wolfSSH_GetPath(ssh->sftpDefaultPath, data + idx, sz, dir, &dirSz)
2015+
!= WS_SUCCESS) {
2016+
WLOG(WS_LOG_SFTP, "Creating path for file to open failed");
2017+
return WS_FATAL_ERROR;
20172018
}
20182019
idx += sz;
20192020

@@ -2128,7 +2129,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
21282129
{
21292130
/* WS_SFTP_FILEATRB atr;*/
21302131
HANDLE fileHandle;
2131-
word32 sz;
2132+
word32 sz, dirSz;
21322133
char dir[WOLFSSH_MAX_FILENAME];
21332134
word32 reason;
21342135
word32 idx = 0;
@@ -2165,9 +2166,11 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
21652166
return WS_BUFFER_E;
21662167
}
21672168

2168-
if (GetAndCleanPath(ssh->sftpDefaultPath,
2169-
data + idx, sz, dir, sizeof(dir)) < 0) {
2170-
return WS_BUFFER_E;
2169+
dirSz = sizeof(dir);
2170+
if (wolfSSH_GetPath(ssh->sftpDefaultPath, data + idx, sz, dir, &dirSz)
2171+
!= WS_SUCCESS) {
2172+
WLOG(WS_LOG_SFTP, "Creating path for file to open failed");
2173+
return WS_FATAL_ERROR;
21712174
}
21722175
idx += sz;
21732176

wolfssh/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,12 @@ typedef struct HandshakeInfo {
620620
} privKey;
621621
} HandshakeInfo;
622622

623+
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
624+
!defined(NO_WOLFSSH_SERVER)
625+
WOLFSSH_LOCAL int wolfSSH_GetPath(const char* defaultPath, byte* in,
626+
word32 inSz, char* out, word32* outSz);
627+
#endif
628+
623629
#ifdef WOLFSSH_SFTP
624630
#define WOLFSSH_MAX_SFTPOFST 3
625631

wolfssh/port.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,14 @@ extern "C" {
575575
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
576576
#endif
577577

578+
#ifndef WOLFSSH_SFTP_DELIM
579+
/* Delimiter's used between two SFTP peers should be the same regardless of
580+
* operating system. WS_DELIM defined elsewhere is OS specific delimiter. */
581+
#define WOLFSSH_SFTP_DELIM "/\\"
582+
#define WOLFSSH_SFTP_IS_DELIM(x) ((x) == '/' || (x) == '\\')
583+
#define WOLFSSH_SFTP_IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
584+
#endif
585+
578586
#if (defined(WOLFSSH_SFTP) || \
579587
defined(WOLFSSH_SCP) || defined(WOLFSSH_SSHD)) && \
580588
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)

0 commit comments

Comments
 (0)