Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented WOLFSSH_FTP_FSETSTAT #551

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 130 additions & 2 deletions src/wolfsftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,11 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
wolfSSH_SFTP_buffer_data(&state->buffer),
wolfSSH_SFTP_buffer_size(&state->buffer));
break;
case WOLFSSH_FTP_FSETSTAT:
ret = wolfSSH_SFTP_RecvFSetSTAT(ssh, state->reqId,
wolfSSH_SFTP_buffer_data(&state->buffer),
wolfSSH_SFTP_buffer_size(&state->buffer));
break;
#endif

#ifndef NO_WOLFSSH_DIR
Expand Down Expand Up @@ -5002,8 +5007,10 @@ static int SFTP_SetFileAttributes(WOLFSSH* ssh, char* name, WS_SFTP_FILEATRB* at
#endif

/* check if time attribute present */
if (atr->flags & WOLFSSH_FILEATRB_TIME) {
/* @TODO set time */
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_TIME)) {
if (WSETTIME(ssh->fs, name, atr->atime, atr->mtime) != 0) {
ret = WS_BAD_FILE_E;
}
}

/* check if extended attributes are present */
Expand All @@ -5016,6 +5023,47 @@ static int SFTP_SetFileAttributes(WOLFSSH* ssh, char* name, WS_SFTP_FILEATRB* at
}


/* sets a files attributes
* returns WS_SUCCESS on success */
static int SFTP_SetFileAttributesHandle(WOLFSSH* ssh, WFD handle, WS_SFTP_FILEATRB* atr)
{
int ret = WS_SUCCESS;

/* check if size attribute present */
if (atr->flags & WOLFSSH_FILEATRB_SIZE) {
/* @TODO set file size */
}

/* check if uid and gid attribute present */
if (atr->flags & WOLFSSH_FILEATRB_UIDGID) {
/* @TODO set group and user id */
}

#ifndef USE_WINDOWS_API
/* check if permissions attribute present */
if (atr->flags & WOLFSSH_FILEATRB_PERM) {
if (WFCHMOD(ssh->fs, handle, atr->per) != 0) {
ret = WS_BAD_FILE_E;
}
}
#endif

/* check if time attribute present */
if (ret == WS_SUCCESS && (atr->flags & WOLFSSH_FILEATRB_TIME)) {
if (WFSETTIME(ssh->fs, handle, atr->atime, atr->mtime) != 0) {
ret = WS_BAD_FILE_E;
}
}

/* check if extended attributes are present */
if (atr->flags & WOLFSSH_FILEATRB_EXT) {
/* @TODO handle extensions */
}

(void)ssh;
return ret ;
}

/* Handles a packet sent to set attributes of path
*
* returns WS_SUCCESS on success
Expand Down Expand Up @@ -5097,6 +5145,86 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return ret;
}


/* Handles a packet sent to set attributes of file handle
*
* returns WS_SUCCESS on success
*/
int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
{
WS_SFTP_FILEATRB atr;
int ret = WS_SUCCESS;

WFD fd;
word32 sz;
word32 idx = 0;

byte* out = NULL;
word32 outSz = 0;

char suc[] = "Set Attirbutes";
char ser[] = "Unable to set attributes error";
char per[] = "Unable to parse attributes error";
char* res = suc;
byte type = WOLFSSH_FTP_OK;

if (ssh == NULL) {
return WS_BAD_ARGUMENT;
}

WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_FSETSTAT");

if (maxSz < UINT32_SZ) {
/* not enough for an ato32 call */
return WS_BUFFER_E;
}

/* get file handle */
ato32(data + idx, &sz); idx += UINT32_SZ;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can maxSz be less than 4?

Copy link
Contributor Author

@falemagn falemagn Aug 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you're referring to the line below the one you've commented on.

maxSz is a parameter of the function, and it's basically the size of the buffer, as far as I can tell. It's the same kind of code that is used throughout the wolfsftp.c file and, indeed, the code I suppose you're referring to has been copied and pasted from other functions that need to get the file handle, which predate this PR, like wolfSSH_SFTP_RecvClose.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line I commented is pulling 4 bytes of data from the buffer.

If the maxSz is guaranteed to be more than 4 bytes, then you don't need a check to whether the buffer is big enough. Otherwise a check is needed to ensure there are 4 bytes to read.

Copy link
Contributor Author

@falemagn falemagn Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand now. If that were an issue, then it would be an issue also in wolfSSH_SFTP_RecvClose and all other functions that do the same thing. I didn't delve into the code that deep, I just assumed that if it's correct elsewhere, then it's correct there, given that the way it gets there is the same as for all the other functions.

if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) {
return WS_BUFFER_E;
}
WMEMSET((byte*)&fd, 0, sizeof(WFD));
WMEMCPY((byte*)&fd, data + idx, sz); idx += sz;

if (ret == WS_SUCCESS &&
SFTP_ParseAtributes_buffer(ssh, &atr, data, &idx, maxSz) != 0) {
type = WOLFSSH_FTP_FAILURE;
res = per;
ret = WS_BAD_FILE_E;
}



/* try to set file attributes and send status back to client */
if (ret == WS_SUCCESS && (ret = SFTP_SetFileAttributesHandle(ssh, fd, &atr))
!= WS_SUCCESS) {
/* tell peer that was not ok */
WLOG(WS_LOG_SFTP, "Unable to get set attributes of open file");
type = WOLFSSH_FTP_FAILURE;
res = ser;
ret = WS_BAD_FILE_E;
}

if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL,
&outSz) != WS_SIZE_ONLY) {
return WS_FATAL_ERROR;
}
out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER);
if (out == NULL) {
return WS_MEMORY_E;
}
if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", out,
&outSz) != WS_SUCCESS) {
WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER);
return WS_FATAL_ERROR;
}

/* set send out buffer, "out" is taken by ssh */
wolfSSH_SFTP_RecvSetSend(ssh, out, outSz);
return ret;
}

#endif /* _WIN32_WCE */
#endif /* !NO_WOLFSSH_SERVER */

Expand Down
4 changes: 4 additions & 0 deletions wolfssh/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@ extern "C" {
#define WREWIND(fs,s) rewind((s))
#define WSEEK_END SEEK_END
#define WBADFILE NULL
#define WSETTIME(fs,f,a,m) (0)
#define WFSETTIME(fs,fd,a,m) (0)
#ifdef WOLFSSL_VXWORKS
#define WUTIMES(f,t) (WS_SUCCESS)
#elif defined(USE_WINDOWS_API)
Expand All @@ -380,8 +382,10 @@ extern "C" {

#ifndef USE_WINDOWS_API
#define WCHMOD(fs,f,m) chmod((f),(m))
#define WFCHMOD(fs,fd,m) fchmod((fd),(m))
#else
#define WCHMOD(fs,f,m) _chmod((f),(m))
#define WFCHMOD(fs,fd,m) _fchmod((fd),(m))
#endif

#if (defined(WOLFSSH_SCP) || \
Expand Down
2 changes: 2 additions & 0 deletions wolfssh/wolfsftp.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ WOLFSSH_LOCAL int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data,
word32 maxSz);
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data,
word32 maxSz);
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data,
word32 maxSz);

#ifndef NO_WOLFSSH_DIR
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data,
Expand Down
Loading