Skip to content

Commit 6f57587

Browse files
authored
Merge pull request #436 from ejohnstown/sftp-list
2 parents 43dce94 + fe2d686 commit 6f57587

File tree

7 files changed

+483
-380
lines changed

7 files changed

+483
-380
lines changed

examples/echoserver/echoserver.c

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,6 +2030,57 @@ static int wsUserAuth(byte authType,
20302030
}
20312031

20322032

2033+
#ifdef WOLFSSH_SFTP
2034+
/*
2035+
* Sets the WOLFSSH object's default SFTP path to the value provided by
2036+
* defaultSftpPath, or uses the current working directory from where the
2037+
* echoserver is run. The new default path is cleaned up with the real
2038+
* path function.
2039+
*
2040+
* @param ssh WOLFSSH object to update
2041+
* @param defaultSftpPath command line provided default SFTP path
2042+
* @return 0 for success or error code
2043+
*/
2044+
static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath)
2045+
{
2046+
char path[WOLFSSH_MAX_FILENAME];
2047+
char realPath[WOLFSSH_MAX_FILENAME];
2048+
int ret = 0;
2049+
2050+
if (defaultSftpPath == NULL) {
2051+
#ifdef USE_WINDOWS_API
2052+
if (GetCurrentDirectoryA(sizeof(path)-1, path) == 0) {
2053+
ret = WS_INVALID_PATH_E;
2054+
}
2055+
#else
2056+
if (getcwd(path, sizeof(path)-1) == NULL) {
2057+
ret = WS_INVALID_PATH_E;
2058+
}
2059+
#endif
2060+
}
2061+
else {
2062+
if (WSTRLEN(defaultSftpPath) >= sizeof(path)) {
2063+
ret = WS_INVALID_PATH_E;
2064+
}
2065+
else {
2066+
WSTRNCPY(path, defaultSftpPath, sizeof(path));
2067+
}
2068+
}
2069+
2070+
if (ret == 0) {
2071+
path[sizeof(path) - 1] = 0;
2072+
ret = wolfSSH_RealPath(NULL, path, realPath, sizeof(realPath));
2073+
}
2074+
2075+
if (ret == WS_SUCCESS) {
2076+
ret = wolfSSH_SFTP_SetDefaultPath(ssh, realPath);
2077+
}
2078+
2079+
return ret;
2080+
}
2081+
#endif
2082+
2083+
20332084
static void ShowUsage(void)
20342085
{
20352086
printf("echoserver %s\n", LIBWOLFSSH_VERSION_STRING);
@@ -2451,12 +2502,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
24512502
}
24522503

24532504
#ifdef WOLFSSH_SFTP
2454-
if (defaultSftpPath) {
2455-
if (wolfSSH_SFTP_SetDefaultPath(ssh, defaultSftpPath)
2456-
!= WS_SUCCESS) {
2457-
fprintf(stderr, "Couldn't store default sftp path.\n");
2458-
WEXIT(EXIT_FAILURE);
2459-
}
2505+
if (SetDefaultSftpPath(ssh, defaultSftpPath) != 0) {
2506+
fprintf(stderr, "Couldn't store default sftp path.\n");
2507+
WEXIT(EXIT_FAILURE);
24602508
}
24612509
#endif
24622510

src/port.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,25 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
166166

167167
#if defined(USE_WINDOWS_API) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP))
168168

169+
/*
170+
* SFTP paths all start with a leading root "/". Most Windows file routines
171+
* expect a drive letter when dealing with an absolute path. If the provided
172+
* path, f, is of the form "/C:...", adjust the pointer f to point to the "C",
173+
* and decrement the file path size, fSz, by one.
174+
*
175+
* @param f pointer to a file name
176+
* @param fSz size of f in bytes
177+
* @return pointer to somewhere in f
178+
*/
179+
static const char* TrimFileName(const char* f, size_t* fSz)
180+
{
181+
if (f != NULL && fSz != NULL && *fSz >= 3 && f[0] == '/' && f[2] == ':') {
182+
f++;
183+
*fSz--;
184+
}
185+
return f;
186+
}
187+
169188
void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
170189
unsigned long shareMode, unsigned long creationDisposition,
171190
unsigned long flags, void* heap)
@@ -178,6 +197,8 @@ void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
178197
errno_t error;
179198

180199
fileNameSz = WSTRLEN(fileName);
200+
fileName = TrimFileName(fileName, &fileNameSz);
201+
181202
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
182203
if (error)
183204
return INVALID_HANDLE_VALUE;
@@ -211,6 +232,8 @@ void* WS_FindFirstFileA(const char* fileName,
211232
errno_t error;
212233

213234
fileNameSz = WSTRLEN(fileName);
235+
fileName = TrimFileName(fileName, &fileNameSz);
236+
214237
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
215238
if (error)
216239
return INVALID_HANDLE_VALUE;
@@ -268,6 +291,8 @@ int WS_GetFileAttributesExA(const char* fileName, void* fileInfo, void* heap)
268291
errno_t error;
269292

270293
fileNameSz = WSTRLEN(fileName);
294+
fileName = TrimFileName(fileName, &fileNameSz);
295+
271296
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
272297
if (error != 0)
273298
return 0;
@@ -301,6 +326,8 @@ int WS_RemoveDirectoryA(const char* dirName, void* heap)
301326
errno_t error;
302327

303328
dirNameSz = WSTRLEN(dirName);
329+
dirName = TrimFileName(dirName, &dirNameSz);
330+
304331
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
305332
if (error != 0)
306333
return 0;
@@ -333,6 +360,8 @@ int WS_CreateDirectoryA(const char* dirName, void* heap)
333360
errno_t error;
334361

335362
dirNameSz = WSTRLEN(dirName);
363+
dirName = TrimFileName(dirName, &dirNameSz);
364+
336365
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
337366
if (error != 0)
338367
return 0;
@@ -368,6 +397,7 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
368397
errno_t error;
369398

370399
oldNameSz = WSTRLEN(oldName);
400+
oldName = TrimFileName(oldName, &oldNameSz);
371401

372402
error = mbstowcs_s(&unicodeOldNameSz, NULL, 0, oldName, 0);
373403
if (error != 0)
@@ -382,6 +412,8 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
382412
oldName, oldNameSz);
383413

384414
newNameSz = WSTRLEN(newName);
415+
newName = TrimFileName(newName, &newNameSz);
416+
385417
error = mbstowcs_s(&unicodeNewNameSz, NULL, 0, newName, 0);
386418
if (error != 0)
387419
return 0;
@@ -417,6 +449,8 @@ int WS_DeleteFileA(const char* fileName, void* heap)
417449
errno_t error;
418450

419451
fileNameSz = WSTRLEN(fileName);
452+
fileName = TrimFileName(fileName, &fileNameSz);
453+
420454
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
421455
if (error != 0)
422456
return 0;

src/ssh.c

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,57 +2274,64 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel)
22742274

22752275
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
22762276
!defined(NO_WOLFSSH_SERVER)
2277+
2278+
#define DELIM "/\\"
2279+
#define IS_DELIM(x) ((x) == '/' || (x) == '\\')
2280+
#define IS_WINPATH(x,y) ((x) > 1 && (y)[1] == ':')
2281+
22772282
/*
2278-
* Paths starting with a slash are absolute, rooted at root. Any path that
2279-
* doesn't have a starting slash is assumed to be relative to the current
2283+
* Paths starting with a slash are absolute, rooted at "/". Any path that
2284+
* doesn't have a starting slash is assumed to be relative to the default
22802285
* path. If the path is empty, return the default path.
22812286
*
22822287
* The path "/." is stripped out. The path "/.." strips out the previous
22832288
* path value. The root path, "/", is always present.
22842289
*
22852290
* Example: "/home/fred/frob/frizz/../../../barney/bar/baz/./././../.."
22862291
* will return "/home/barney". "/../.." will return "/". "." will return
2287-
* currentPath.
2292+
* the default path.
22882293
*
22892294
* Note, this function does not care about OS and filesystem issues. The
22902295
* SFTP protocol describes how paths are handled in SFTP. Specialized
22912296
* behaviors are handled when actually calling the OS functions. Paths
22922297
* are further massaged there. For example, the C: drive is treated as
22932298
* the path "/C:", and is a directory like any other.
22942299
*
2295-
* @param currentPath RealPath of the current working directory
22962300
* @param defaultPath RealPath of the default directory, usually user's
22972301
* @param in requested new path
22982302
* @param out output of real path cleanup
22992303
* @param outSz size in bytes of buffer 'out'
23002304
* @return WS_SUCCESS, WS_BAD_ARGUMENT, or WS_INVALID_PATH_E
23012305
*/
2302-
int wolfSSH_RealPath(const char* currentPath, const char* defaultPath,
2303-
char* in, char* out, word32 outSz)
2306+
int wolfSSH_RealPath(const char* defaultPath, char* in,
2307+
char* out, word32 outSz)
23042308
{
23052309
char* tail = NULL;
23062310
char* seg;
23072311
word32 inSz, segSz, curSz;
23082312

2309-
if (currentPath == NULL || defaultPath == NULL ||
2310-
in == NULL || out == NULL || outSz == 0)
2313+
if (in == NULL || out == NULL || outSz == 0) {
23112314
return WS_BAD_ARGUMENT;
2315+
}
23122316

23132317
WMEMSET(out, 0, outSz);
23142318
inSz = (word32)WSTRLEN(in);
2315-
if (inSz == 0) {
2316-
WSTRNCPY(out, defaultPath, outSz);
2317-
}
2318-
else if (in[0] == '/') {
2319-
out[0] = '/';
2320-
}
2321-
else {
2322-
WSTRNCPY(out, currentPath, outSz);
2319+
out[0] = '/';
2320+
curSz = 1;
2321+
if (inSz == 0 || (!IS_DELIM(in[0]) && !IS_WINPATH(inSz, in))) {
2322+
if (defaultPath != NULL) {
2323+
curSz = (word32)WSTRLEN(defaultPath);
2324+
if (curSz >= outSz) {
2325+
return WS_INVALID_PATH_E;
2326+
}
2327+
WSTRNCPY(out, defaultPath, outSz);
2328+
}
23232329
}
2324-
out[outSz - 1] = 0;
2325-
curSz = (word32)WSTRLEN(out);
2330+
out[curSz] = 0;
23262331

2327-
for (seg = WSTRTOK(in, "/", &tail); seg; seg = WSTRTOK(NULL, "/", &tail)) {
2332+
for (seg = WSTRTOK(in, DELIM, &tail);
2333+
seg;
2334+
seg = WSTRTOK(NULL, DELIM, &tail)) {
23282335
segSz = (word32)WSTRLEN(seg);
23292336

23302337
/* Try to match "." */
@@ -2349,6 +2356,10 @@ int wolfSSH_RealPath(const char* currentPath, const char* defaultPath,
23492356
}
23502357
/* Everything else is copied */
23512358
else {
2359+
if (curSz >= outSz - segSz) {
2360+
return WS_INVALID_PATH_E;
2361+
}
2362+
23522363
if (curSz != 1) {
23532364
WSTRNCAT(out, "/", outSz - curSz);
23542365
curSz++;

0 commit comments

Comments
 (0)