Skip to content

Commit 8c7be35

Browse files
wolfsftp, port: apply the attributes SETSTAT and FSETSTAT acknowledge
- SFTP_SetFileAttributes() and SFTP_SetFileAttributesHandle() carry out the size, ownership, permission and timestamp requests while ret is WS_SUCCESS, bound the size with wResolveOffset() against WOLFSSH_MAX_FILE_OFFSET, and set WS_UNIMPLEMENTED_E where the port defines no wrapper. - wolfSSH_SFTP_RecvSetSTAT() and wolfSSH_SFTP_RecvFSetSTAT() answer WOLFSSH_FTP_UNSUPPORTED for WS_UNIMPLEMENTED_E; wolfSSH_SFTP_CHMOD() sets the attribute flags to WOLFSSH_FILEATRB_PERM before sending. - port.h adds WTRUNCATE, WFTRUNCATE, WCHOWN and WFCHOWN for the POSIX port, and defines WSETTIME and WFSETTIME over the existing WUTIMES and WFUTIMES helpers in place of their (0) definitions. - SFTP_SetMode() guards on _WIN32_WCE in place of USE_WINDOWS_API, and port.c adds WS_ChmodA(), which trims the SFTP leading root and calls _wchmod(); it and the WCHMOD mapping to it are left out under _WIN32_WCE, which keeps the _chmod mapping. - tests/regress.c adds TestSftpSetStatAttributes(); tests/sftp.c adds a chmod of a directory and installs SFTP_TEST_UMASK in place of the sftpTestUmask static; the STATE_SET_ATR_SEND case in tests/api.c sets atr.flags to WOLFSSH_FILEATRB_PERM. Issue: F-11658
1 parent 78633a1 commit 8c7be35

6 files changed

Lines changed: 485 additions & 37 deletions

File tree

src/port.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,44 @@ int WS_DeleteFileA(const char* fileName, void* heap)
542542
}
543543

544544

545+
546+
#ifndef _WIN32_WCE
547+
548+
int WS_ChmodA(const char* fileName, int mode, void* heap)
549+
{
550+
int ret = -1;
551+
wchar_t* unicodeFileName;
552+
size_t unicodeFileNameSz = 0;
553+
size_t returnSz = 0;
554+
size_t fileNameSz = 0;
555+
errno_t error;
556+
557+
fileNameSz = WSTRLEN(fileName);
558+
fileName = TrimFileName(fileName, &fileNameSz);
559+
560+
error = mbstowcs_s(&unicodeFileNameSz, NULL, 0, fileName, 0);
561+
if (error != 0)
562+
return -1;
563+
564+
unicodeFileName = (wchar_t*)WMALLOC((unicodeFileNameSz+1)*sizeof(wchar_t),
565+
heap, PORT_DYNTYPE_STRING);
566+
if (unicodeFileName == NULL)
567+
return -1;
568+
569+
error = mbstowcs_s(&returnSz, unicodeFileName, unicodeFileNameSz,
570+
fileName, fileNameSz);
571+
572+
if (error == 0) {
573+
ret = _wchmod(unicodeFileName, mode);
574+
}
575+
576+
WFREE(unicodeFileName, heap, PORT_DYNTYPE_STRING);
577+
578+
return ret;
579+
}
580+
581+
#endif /* !_WIN32_WCE */
582+
545583
#endif /* USE_WINDOWS_API WOLFSSH_SFTP WOLFSSH_SCP */
546584

547585
#if !defined(NO_FILESYSTEM) && \

src/wolfsftp.c

Lines changed: 80 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6046,7 +6046,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
60466046
return ret;
60476047
}
60486048

6049-
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) \
6049+
#if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR) \
60506050
&& !defined(WOLFSSH_SFTP_SETMODE) && !defined(WOLFSSH_FATFS)
60516051
/* Set the files mode
60526052
* return WS_SUCCESS on success */
@@ -6082,29 +6082,47 @@ static int SFTP_SetFileAttributes(WOLFSSH* ssh,
60826082
char* name, WS_SFTP_FILEATRB* atr)
60836083
{
60846084
int ret = WS_SUCCESS;
6085+
#ifdef WTRUNCATE
6086+
word64 sz;
6087+
#endif
60856088

60866089
/* check if size attribute present */
6087-
if (atr->flags & WOLFSSH_FILEATRB_SIZE) {
6088-
/* @TODO set file size */
6090+
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_SIZE)) {
6091+
#ifdef WTRUNCATE
6092+
if (wResolveOffset(atr->sz, WOLFSSH_MAX_FILE_OFFSET, &sz) != 0
6093+
|| WTRUNCATE(ssh->fs, name, sz) != 0) {
6094+
ret = WS_BAD_FILE_E;
6095+
}
6096+
#else
6097+
ret = WS_UNIMPLEMENTED_E;
6098+
#endif
60896099
}
60906100

60916101
/* check if uid and gid attribute present */
6092-
if (atr->flags & WOLFSSH_FILEATRB_UIDGID) {
6093-
/* @TODO set group and user id */
6102+
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_UIDGID)) {
6103+
#ifdef WCHOWN
6104+
if (WCHOWN(ssh->fs, name, atr->uid, atr->gid) != 0) {
6105+
ret = WS_BAD_FILE_E;
6106+
}
6107+
#else
6108+
ret = WS_UNIMPLEMENTED_E;
6109+
#endif
60946110
}
60956111

6096-
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR)
60976112
/* check if permissions attribute present */
6098-
if (atr->flags & WOLFSSH_FILEATRB_PERM) {
6113+
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_PERM)) {
60996114
ret = SFTP_SetMode(ssh->fs, name, WOLFSSH_SFTP_SAFE_MODE(atr->per));
61006115
}
6101-
#endif
61026116

61036117
/* check if time attribute present */
61046118
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_TIME)) {
6119+
#ifdef WSETTIME
61056120
if (WSETTIME(ssh->fs, name, atr->atime, atr->mtime) != 0) {
61066121
ret = WS_BAD_FILE_E;
61076122
}
6123+
#else
6124+
ret = WS_UNIMPLEMENTED_E;
6125+
#endif
61086126
}
61096127

61106128
/* check if extended attributes are present */
@@ -6128,29 +6146,52 @@ static int SFTP_SetFileAttributesHandle(WOLFSSH* ssh,
61286146
WS_SFTP_FILEATRB* atr)
61296147
{
61306148
int ret = WS_SUCCESS;
6149+
#ifdef WFTRUNCATE
6150+
word64 sz;
6151+
#endif
61316152

61326153
/* check if size attribute present */
6133-
if (atr->flags & WOLFSSH_FILEATRB_SIZE) {
6134-
/* @TODO set file size */
6154+
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_SIZE)) {
6155+
#ifdef WFTRUNCATE
6156+
if (wResolveOffset(atr->sz, WOLFSSH_MAX_FILE_OFFSET, &sz) != 0
6157+
|| WFTRUNCATE(ssh->fs, handle, sz) != 0) {
6158+
ret = WS_BAD_FILE_E;
6159+
}
6160+
#else
6161+
ret = WS_UNIMPLEMENTED_E;
6162+
#endif
61356163
}
61366164

61376165
/* check if uid and gid attribute present */
6138-
if (atr->flags & WOLFSSH_FILEATRB_UIDGID) {
6139-
/* @TODO set group and user id */
6166+
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_UIDGID)) {
6167+
#ifdef WFCHOWN
6168+
if (WFCHOWN(ssh->fs, handle, atr->uid, atr->gid) != 0) {
6169+
ret = WS_BAD_FILE_E;
6170+
}
6171+
#else
6172+
ret = WS_UNIMPLEMENTED_E;
6173+
#endif
61406174
}
61416175

6142-
#ifndef USE_WINDOWS_API
61436176
/* check if permissions attribute present */
6144-
if (atr->flags & WOLFSSH_FILEATRB_PERM) {
6145-
ret = SFTP_SetModeHandle(ssh->fs, handle, WOLFSSH_SFTP_SAFE_MODE(atr->per));
6146-
}
6177+
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_PERM)) {
6178+
#ifndef USE_WINDOWS_API
6179+
ret = SFTP_SetModeHandle(ssh->fs, handle,
6180+
WOLFSSH_SFTP_SAFE_MODE(atr->per));
6181+
#else
6182+
ret = WS_UNIMPLEMENTED_E;
61476183
#endif
6184+
}
61486185

61496186
/* check if time attribute present */
61506187
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_TIME)) {
6188+
#ifdef WFSETTIME
61516189
if (WFSETTIME(ssh->fs, handle, atr->atime, atr->mtime) != 0) {
61526190
ret = WS_BAD_FILE_E;
61536191
}
6192+
#else
6193+
ret = WS_UNIMPLEMENTED_E;
6194+
#endif
61546195
}
61556196

61566197
/* check if extended attributes are present */
@@ -6159,9 +6200,9 @@ static int SFTP_SetFileAttributesHandle(WOLFSSH* ssh,
61596200
}
61606201

61616202
(void)ssh;
6162-
#ifdef USE_WINDOWS_API
6163-
/* On Windows the only consumers (SFTP_SetModeHandle / WFSETTIME) are
6164-
* compiled out or no-ops, so the handle goes unused here. */
6203+
#if defined(USE_WINDOWS_API) && !defined(WFTRUNCATE) && !defined(WFCHOWN) \
6204+
&& !defined(WFSETTIME)
6205+
/* no consumer of the handle is compiled in on this port */
61656206
(void)handle;
61666207
#endif
61676208
return ret ;
@@ -6186,6 +6227,7 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
61866227
char ser[] = "Unable to set attributes error";
61876228
char per[] = "Unable to parse attributes error";
61886229
char pdn[] = "Permission denied";
6230+
char uns[] = "Attribute not supported";
61896231
char* res = suc;
61906232
byte type = WOLFSSH_FTP_OK;
61916233

@@ -6224,8 +6266,14 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
62246266
!= WS_SUCCESS) {
62256267
/* tell peer that was not ok */
62266268
WLOG(WS_LOG_SFTP, "Unable to get set attributes of file/directory");
6227-
type = WOLFSSH_FTP_FAILURE;
6228-
res = ser;
6269+
if (ret == WS_UNIMPLEMENTED_E) {
6270+
type = WOLFSSH_FTP_UNSUPPORTED;
6271+
res = uns;
6272+
}
6273+
else {
6274+
type = WOLFSSH_FTP_FAILURE;
6275+
res = ser;
6276+
}
62296277
ret = WS_BAD_FILE_E;
62306278
}
62316279

@@ -6261,6 +6309,7 @@ int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
62616309
char suc[] = "Set Attributes";
62626310
char ser[] = "Unable to set attributes error";
62636311
char per[] = "Unable to parse attributes error";
6312+
char uns[] = "Attribute not supported";
62646313
char* res = suc;
62656314
byte type = WOLFSSH_FTP_OK;
62666315

@@ -6315,8 +6364,14 @@ int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
63156364
!= WS_SUCCESS) {
63166365
/* tell peer that was not ok */
63176366
WLOG(WS_LOG_SFTP, "Unable to get set attributes of open file");
6318-
type = WOLFSSH_FTP_FAILURE;
6319-
res = ser;
6367+
if (ret == WS_UNIMPLEMENTED_E) {
6368+
type = WOLFSSH_FTP_UNSUPPORTED;
6369+
res = uns;
6370+
}
6371+
else {
6372+
type = WOLFSSH_FTP_FAILURE;
6373+
res = ser;
6374+
}
63206375
ret = WS_BAD_FILE_E;
63216376
}
63226377

@@ -7665,7 +7720,8 @@ int wolfSSH_SFTP_CHMOD(WOLFSSH* ssh, char* n, char* oct)
76657720
break;
76667721
}
76677722

7668-
/* update permissions */
7723+
/* only the permissions change here */
7724+
state->atr.flags = WOLFSSH_FILEATRB_PERM;
76697725
state->atr.per = mode;
76707726
state->state = STATE_CHMOD_SEND;
76717727
FALL_THROUGH;

tests/api.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4848,6 +4848,9 @@ static void test_wolfSSH_SFTP_PartialSend(void)
48484848
wolfSSH_SFTP_Close(ssh, handle, handleSz);
48494849

48504850
if (wolfSSH_SFTP_STAT(ssh, atrName, &atr) == WS_SUCCESS) {
4851+
/* Send only the permissions back. A port without WTRUNCATE
4852+
* answers a size request with SSH_FX_OP_UNSUPPORTED. */
4853+
atr.flags = WOLFSSH_FILEATRB_PERM;
48514854
AssertIntEQ(wolfSSH_TestSftpSendCap(ssh, 1), WS_SUCCESS);
48524855
ret = WS_FATAL_ERROR;
48534856
sawPartial = 0;

0 commit comments

Comments
 (0)