SFTP List

1. Update wolfSSH_SFTPNAME_readdir() to have a special case getting
   the drive letters at root in Windows.
2. The Win32 APIs can use forward slashes, but cannot have one at the
   beginning of the path before the drive letter. Add a trim function
   to remove the leading slash in the SFTP paths.
3. Update echoserver to always set the default SFTP path to either the
   provided command line option or to the CWD for the echoserver run.
4.  Get the RealPath for the default path
5. Tweak wolfSSH_RealPath() to handle some Windows cases.
6. Added more test cases.
pull/436/head
John Safranek 2022-09-16 12:13:09 -07:00
parent 2d3f11634a
commit a48926b0dd
No known key found for this signature in database
GPG Key ID: 8CE817DE0D3CCB4A
5 changed files with 102 additions and 25 deletions

View File

@ -2030,6 +2030,42 @@ static int wsUserAuth(byte authType,
}
#ifdef WOLFSSH_SFTP
static int SetDefaultSftpPath(WOLFSSH* ssh, const char* defaultSftpPath)
{
char path[WOLFSSH_MAX_FILENAME];
char realPath[WOLFSSH_MAX_FILENAME];
int ret = 0;
if (defaultSftpPath == NULL) {
#ifdef USE_WINDOWS_API
if (GetCurrentDirectoryA(sizeof(path), path) == 0) {
ret = -1;
}
#else
if (getcwd(path, sizeof(path)) == NULL) {
ret = -1;
}
#endif
}
else {
WSTRNCPY(path, defaultSftpPath, sizeof(path));
path[sizeof(path) - 1] = 0;
}
if (ret == 0) {
path[sizeof(path) - 1] = 0;
wolfSSH_RealPath(NULL, path, realPath, sizeof(realPath));
if (wolfSSH_SFTP_SetDefaultPath(ssh, realPath) != WS_SUCCESS) {
ret = -1;
}
}
return ret;
}
#endif
static void ShowUsage(void)
{
printf("echoserver %s\n", LIBWOLFSSH_VERSION_STRING);
@ -2451,12 +2487,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
}
#ifdef WOLFSSH_SFTP
if (defaultSftpPath) {
if (wolfSSH_SFTP_SetDefaultPath(ssh, defaultSftpPath)
!= WS_SUCCESS) {
fprintf(stderr, "Couldn't store default sftp path.\n");
WEXIT(EXIT_FAILURE);
}
if (SetDefaultSftpPath(ssh, defaultSftpPath) != 0) {
fprintf(stderr, "Couldn't store default sftp path.\n");
WEXIT(EXIT_FAILURE);
}
#endif

View File

@ -166,6 +166,15 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
#if defined(USE_WINDOWS_API) && (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP))
static const char* TrimFileName(const char* f, size_t* fSz)
{
if (f != NULL && fSz != NULL && *fSz >= 3 && f[0] == '/' && f[2] == ':') {
f++;
*fSz--;
}
return f;
}
void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
unsigned long shareMode, unsigned long creationDisposition,
unsigned long flags, void* heap)
@ -178,6 +187,8 @@ void* WS_CreateFileA(const char* fileName, unsigned long desiredAccess,
errno_t error;
fileNameSz = WSTRLEN(fileName);
fileName = TrimFileName(fileName, &fileNameSz);
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
if (error)
return INVALID_HANDLE_VALUE;
@ -211,6 +222,8 @@ void* WS_FindFirstFileA(const char* fileName,
errno_t error;
fileNameSz = WSTRLEN(fileName);
fileName = TrimFileName(fileName, &fileNameSz);
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
if (error)
return INVALID_HANDLE_VALUE;
@ -268,6 +281,8 @@ int WS_GetFileAttributesExA(const char* fileName, void* fileInfo, void* heap)
errno_t error;
fileNameSz = WSTRLEN(fileName);
fileName = TrimFileName(fileName, &fileNameSz);
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
if (error != 0)
return 0;
@ -301,6 +316,8 @@ int WS_RemoveDirectoryA(const char* dirName, void* heap)
errno_t error;
dirNameSz = WSTRLEN(dirName);
dirName = TrimFileName(dirName, &dirNameSz);
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
if (error != 0)
return 0;
@ -333,6 +350,8 @@ int WS_CreateDirectoryA(const char* dirName, void* heap)
errno_t error;
dirNameSz = WSTRLEN(dirName);
dirName = TrimFileName(dirName, &dirNameSz);
error = mbstowcs_s(&unicodeDirNameSz, NULL, 0, dirName, 0);
if (error != 0)
return 0;
@ -368,6 +387,7 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
errno_t error;
oldNameSz = WSTRLEN(oldName);
oldName = TrimFileName(oldName, &oldNameSz);
error = mbstowcs_s(&unicodeOldNameSz, NULL, 0, oldName, 0);
if (error != 0)
@ -382,6 +402,8 @@ int WS_MoveFileA(const char* oldName, const char* newName, void* heap)
oldName, oldNameSz);
newNameSz = WSTRLEN(newName);
newName = TrimFileName(newName, &newNameSz);
error = mbstowcs_s(&unicodeNewNameSz, NULL, 0, newName, 0);
if (error != 0)
return 0;
@ -417,6 +439,8 @@ int WS_DeleteFileA(const char* fileName, void* heap)
errno_t error;
fileNameSz = WSTRLEN(fileName);
fileName = TrimFileName(fileName, &fileNameSz);
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
if (error != 0)
return 0;

View File

@ -2274,6 +2274,11 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel)
#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
@ -2311,16 +2316,18 @@ int wolfSSH_RealPath(const char* defaultPath, char* in,
WMEMSET(out, 0, outSz);
inSz = (word32)WSTRLEN(in);
if ((inSz == 0 || in[0] != '/') && defaultPath != NULL){
WSTRNCPY(out, defaultPath, outSz);
}
else {
out[0] = '/';
out[0] = '/';
if (inSz == 0 || (!IS_DELIM(in[0]) && !IS_WINPATH(inSz, in))) {
if (defaultPath != NULL) {
WSTRNCPY(out, defaultPath, outSz);
}
}
out[outSz - 1] = 0;
curSz = (word32)WSTRLEN(out);
for (seg = WSTRTOK(in, "/", &tail); seg; seg = WSTRTOK(NULL, "/", &tail)) {
for (seg = WSTRTOK(in, DELIM, &tail);
seg;
seg = WSTRTOK(NULL, DELIM, &tail)) {
segSz = (word32)WSTRLEN(seg);
/* Try to match "." */

View File

@ -2265,8 +2265,10 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
int i;
WMEMSET(ssh->driveList, 0, sizeof ssh->driveList);
ssh->driveListCount = 0;
drives = GetLogicalDrives();
for (i = 0, mask = 1; i < 26; i++, mask <<= 1) {
for (i = 0, mask = 1; i < (sizeof ssh->driveList); i++, mask <<= 1) {
if (drives & mask) {
driveName[0] = 'A' + i;
driveType = GetDriveTypeA(driveName);
@ -2649,7 +2651,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
char* dirName)
{
int sz;
int sz, special = 0;
HANDLE findHandle;
char realFileName[MAX_PATH];
@ -2658,13 +2660,13 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
}
/* special case of getting drives at "/" */
if (dirName[0] == "/" && dirName[1] == 0) {
if (dirName[0] == '/' && dirName[1] == 0) {
if (ssh->driveIdx >= ssh->driveListCount)
return WS_FATAL_ERROR;
realFileName[0] = ssh->driveList[ssh->driveIdx++];
realFileName[1] = ':';
realFileName[2] = '/';
realFileName[3] = '\0';
realFileName[2] = '\0';
special = 1;
}
else if (*dir == INVALID_HANDLE_VALUE) {
char name[MAX_PATH];
@ -2714,16 +2716,21 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
return WS_MEMORY_E;
}
buf[0] = '\0';
WSTRNCAT(buf, dirName, bufSz + 1);
tmpSz = (int)WSTRLEN(buf);
if (!special) {
WSTRNCAT(buf, dirName, bufSz + 1);
tmpSz = (int)WSTRLEN(buf);
/* add delimiter between path and file/dir name */
if (tmpSz + 1 < bufSz) {
buf[tmpSz] = WS_DELIM;
buf[tmpSz + 1] = '\0';
/* add delimiter between path and file/dir name */
if (tmpSz + 1 < bufSz) {
buf[tmpSz] = WS_DELIM;
buf[tmpSz + 1] = '\0';
}
WSTRNCAT(buf, out->fName, bufSz + 1);
}
else {
WSTRNCAT(buf, realFileName, bufSz + 1);
WSTRNCAT(buf, "\\", bufSz + 1);
}
WSTRNCAT(buf, out->fName, bufSz + 1);
if (SFTP_GetAttributes(ssh->fs, buf, &out->atrb, 0, ssh->ctx->heap)
!= WS_SUCCESS) {
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s",

View File

@ -1050,6 +1050,12 @@ struct RealPathTestCase realPathDefault[] = {
{ "./sample.jpg", "/C:/Users/fred/sample.jpg" },
{ "./sample./other", "/C:/Users/fred/sample./other" },
{ "./sample.dir/other", "/C:/Users/fred/sample.dir/other" },
{ "\\C:\\Users\\fred\\Documents\\junk.txt",
"/C:/Users/fred/Documents/junk.txt" },
{ "C:\\Users\\fred\\Documents\\junk.txt",
"/C:/Users/fred/Documents/junk.txt" },
{ "/C:\\Users\\fred/Documents\\junk.txt",
"/C:/Users/fred/Documents/junk.txt" },
};
struct RealPathTestCase realPathNull[] = {