mirror of https://github.com/wolfSSL/wolfssh.git
commit
419efeb59c
|
@ -35,6 +35,7 @@
|
|||
#ifdef WOLFSSL_NUCLEUS
|
||||
/* use buffers for keys with server */
|
||||
#define NO_FILESYSTEM
|
||||
#define WOLFSSH_NO_EXIT
|
||||
#endif
|
||||
|
||||
#ifdef NO_FILESYSTEM
|
||||
|
@ -210,6 +211,12 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
|
|||
break;
|
||||
}
|
||||
|
||||
if (ret == WS_FATAL_ERROR && wolfSSH_get_error(threadCtx->ssh) ==
|
||||
WS_VERSION_E) {
|
||||
ret = 0; /* don't break out of loop with version miss match */
|
||||
printf("Unsupported version error\n");
|
||||
}
|
||||
|
||||
if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) {
|
||||
fprintf(stderr, "Error with SSH shutdown.\n");
|
||||
}
|
||||
|
@ -220,7 +227,9 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
|
|||
if (ret != 0) {
|
||||
fprintf(stderr, "Error [%d] \"%s\" with handling connection.\n", ret,
|
||||
wolfSSH_ErrorToName(ret));
|
||||
#ifndef WOLFSSH_NO_EXIT
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
free(threadCtx);
|
||||
|
|
|
@ -7151,3 +7151,59 @@ void DumpOctetString(const byte* input, word32 inputSz)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* converts the octal input to decimal. Input is in string format i.e. 0666
|
||||
* returns the decimal value on success or negative value on failure */
|
||||
int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
|
||||
defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
|
||||
defined(WOLFSSL_PUBLIC_MP)
|
||||
mp_int tmp;
|
||||
char decimalString[WOLFSSH_MAX_OCTET_LEN + 1];
|
||||
#else
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (octSz > WOLFSSH_MAX_OCTET_LEN || ssh == NULL || oct == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
|
||||
defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
|
||||
defined(WOLFSSL_PUBLIC_MP)
|
||||
ret = mp_init(&tmp);
|
||||
if (ret == MP_OKAY) {
|
||||
ret = mp_read_radix(&tmp, (const char*)oct, 8);
|
||||
}
|
||||
|
||||
if (ret == MP_OKAY) {
|
||||
/* convert octal to decimal */
|
||||
ret = mp_todecimal(&tmp, decimalString);
|
||||
|
||||
if (ret == MP_OKAY) {
|
||||
/* convert string to int */
|
||||
ret = atoi(decimalString);
|
||||
}
|
||||
}
|
||||
mp_clear(&tmp);
|
||||
#else
|
||||
/* convert octal string to int without mp_read_radix() */
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < WOLFSSH_MAX_OCTET_LEN; i++)
|
||||
{
|
||||
if (oct[i] < '0' || oct[0] > '7') {
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
break;
|
||||
}
|
||||
ret <<= 3;
|
||||
ret |= (oct[i] - '0');
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,11 @@ void wolfSSH_free(WOLFSSH* ssh)
|
|||
|
||||
if (ssh) {
|
||||
void* heap = ssh->ctx ? ssh->ctx->heap : NULL;
|
||||
#ifdef WOLFSSH_SFTP
|
||||
if (wolfSSH_SFTP_free(ssh) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Error cleaning up SFTP connection");
|
||||
}
|
||||
#endif
|
||||
SshResourceFree(ssh, heap);
|
||||
WFREE(ssh, heap, DYNTYPE_SSH);
|
||||
}
|
||||
|
@ -930,5 +935,3 @@ const char* wolfSSH_GetSessionCommand(const WOLFSSH* ssh)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -827,6 +827,7 @@ static int GetScpFileMode(WOLFSSH* ssh, byte* buf, word32 bufSz,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Locates first space present in given string (buf) and sets inOutIdx
|
||||
* to that offset.
|
||||
*
|
||||
|
|
466
src/wolfsftp.c
466
src/wolfsftp.c
|
@ -43,7 +43,8 @@ static int SFTP_ParseAtributes_buffer(WOLFSSH* ssh, WS_SFTP_FILEATRB* atr,
|
|||
byte* buf, word32 bufSz);
|
||||
static int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr,
|
||||
byte link);
|
||||
static int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr);
|
||||
static int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
|
||||
WS_SFTP_FILEATRB* atr);
|
||||
static WS_SFTPNAME* wolfSSH_SFTPNAME_new(void* heap);
|
||||
|
||||
/* Gets packet header information
|
||||
|
@ -127,8 +128,7 @@ static int SFTP_ServerRecvInit(WOLFSSH* ssh) {
|
|||
|
||||
ato32(buf + LENGTH_SZ + MSG_ID_SZ, &version);
|
||||
if (version != WOLFSSH_SFTP_VERSION) {
|
||||
WLOG(WS_LOG_SFTP, "Unsupported SFTP version");
|
||||
return WS_FATAL_ERROR;
|
||||
WLOG(WS_LOG_SFTP, "Unsupported SFTP version, sending version 3");
|
||||
}
|
||||
|
||||
/* silently ignore extensions if not supported */
|
||||
|
@ -263,7 +263,7 @@ static int SFTP_AtributesSz(WOLFSSH* ssh, WS_SFTP_FILEATRB* atr)
|
|||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
static int SFTP_SetAtributes(WOLFSSH* ssh, byte* buf, word32 bufSz,
|
||||
static int SFTP_SetAttributes(WOLFSSH* ssh, byte* buf, word32 bufSz,
|
||||
WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
word32 idx = 0;
|
||||
|
@ -396,7 +396,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
|||
WMEMCPY(out + idx, r, rSz); idx += rSz;
|
||||
|
||||
/* set attributes */
|
||||
SFTP_SetAtributes(ssh, out + idx, maxSz - idx, &atr);
|
||||
SFTP_SetAttributes(ssh, out + idx, maxSz - idx, &atr);
|
||||
|
||||
/* send out buffer */
|
||||
if (wolfSSH_stream_send(ssh, out, maxSz) < 0) {
|
||||
|
@ -464,7 +464,10 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
|
|||
case WOLFSSH_FTP_RENAME:
|
||||
return wolfSSH_SFTP_RecvRename(ssh, reqId, maxSz);
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
case WOLFSSH_FTP_SETSTAT:
|
||||
return wolfSSH_SFTP_RecvSetSTAT(ssh, reqId, maxSz);
|
||||
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
case WOLFSSH_FTP_OPENDIR:
|
||||
return wolfSSH_SFTP_RecvOpenDir(ssh, reqId, maxSz);
|
||||
|
||||
|
@ -673,7 +676,8 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
if (sz != UINT32_SZ) {
|
||||
WLOG(WS_LOG_SFTP, "Attribute size larger than 4 not yet supported");
|
||||
WLOG(WS_LOG_SFTP, "Skipping over attribute");
|
||||
WLOG(WS_LOG_SFTP, "Skipping over attribute and using default");
|
||||
mode = 0x41ED;
|
||||
}
|
||||
else {
|
||||
ato32(data + idx, &mode);
|
||||
|
@ -811,13 +815,14 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
}
|
||||
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
|
||||
/* hold pointers to directory handles */
|
||||
typedef struct DIR_HANDLE {
|
||||
WDIR dir;
|
||||
byte isEof; /* flag for if read everything */
|
||||
word64 id; /* handle ID */
|
||||
char* dirName; /* base name of directory */
|
||||
byte isEof; /* flag for if read everything */
|
||||
word64 id; /* handle ID */
|
||||
struct DIR_HANDLE* next;
|
||||
} DIR_HANDLE;
|
||||
static DIR_HANDLE* dirList = NULL;
|
||||
|
@ -881,7 +886,6 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
"Unable To Open Directory", "English");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
(void)reqId;
|
||||
|
||||
|
@ -890,6 +894,7 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
dirList = (DIR_HANDLE*)WMALLOC(sizeof(DIR_HANDLE), ssh->ctx->heap,
|
||||
DYNTYPE_SFTP);
|
||||
if (dirList == NULL) {
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
|
@ -900,6 +905,7 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
dirList->id = idCount++;
|
||||
dirList->isEof = 0;
|
||||
dirList->next = NULL;
|
||||
dirList->dirName = dir; /* take over ownership of buffer */
|
||||
SendPacketType(ssh, WOLFSSH_FTP_HANDLE, (byte*)&dirList->id,
|
||||
sizeof(word64));
|
||||
}
|
||||
|
@ -907,6 +913,7 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
DIR_HANDLE* cur = (DIR_HANDLE*)WMALLOC(sizeof(DIR_HANDLE),
|
||||
ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
if (cur == NULL) {
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
|
@ -918,6 +925,7 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
cur->isEof = 0;
|
||||
cur->next = dirList;
|
||||
dirList = cur;
|
||||
dirList->dirName = dir; /* take over ownership of buffer */
|
||||
SendPacketType(ssh, WOLFSSH_FTP_HANDLE, (byte*)&cur->id,
|
||||
sizeof(word64));
|
||||
}
|
||||
|
@ -933,7 +941,8 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -941,12 +950,14 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
|||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
sz = (int)WSTRLEN(dir->sfname);
|
||||
/* use long name on Nucleus because sfname has only the file name and in all
|
||||
* caps */
|
||||
sz = (int)WSTRLEN(dir->lfname);
|
||||
out->fName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (out->fName == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
WMEMCPY(out->fName, dir->sfname, sz);
|
||||
WMEMCPY(out->fName, dir->lfname, sz);
|
||||
out->fName[sz] = '\0';
|
||||
out->fSz = sz;
|
||||
|
||||
|
@ -959,7 +970,33 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
|||
out->lName[sz] = '\0';
|
||||
out->lSz = sz;
|
||||
|
||||
SFTP_GetAttributes(out->fName, &out->atrb, 0);
|
||||
{
|
||||
char* buf;
|
||||
int bufSz;
|
||||
int tmpSz;
|
||||
|
||||
bufSz = out->fSz + WSTRLEN(dirName) + sizeof(WS_DELIM);
|
||||
buf = (char*)WMALLOC(bufSz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (buf == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
buf[0] = '\0';
|
||||
WSTRNCAT(buf, dirName, bufSz);
|
||||
tmpSz = WSTRLEN(buf);
|
||||
|
||||
/* 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);
|
||||
|
||||
clean_path(buf);
|
||||
if (SFTP_GetAttributes(buf, &out->atrb, 0) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s", buf);
|
||||
}
|
||||
WFREE(buf, out->heap, DYNTYPE_SFTP);
|
||||
}
|
||||
|
||||
if ((WREADDIR(dir)) == NULL) {
|
||||
return WS_NEXT_ERROR;
|
||||
|
@ -973,7 +1010,8 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
|||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
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)
|
||||
{
|
||||
struct dirent* dp;
|
||||
int sz;
|
||||
|
@ -1006,8 +1044,33 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
|||
out->lSz = sz;
|
||||
|
||||
/* attempt to get file attributes. Could be directory or have none */
|
||||
if (SFTP_GetAttributes(out->fName, &out->atrb, 0) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s", out->fName);
|
||||
{
|
||||
char* buf;
|
||||
int bufSz;
|
||||
int tmpSz;
|
||||
|
||||
bufSz = out->fSz + (int)WSTRLEN(dirName) + sizeof(WS_DELIM);
|
||||
buf = (char*)WMALLOC(bufSz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (buf == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
buf[0] = '\0';
|
||||
WSTRNCAT(buf, dirName, bufSz);
|
||||
tmpSz = (int)WSTRLEN(buf);
|
||||
|
||||
/* 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);
|
||||
|
||||
clean_path(buf);
|
||||
if (SFTP_GetAttributes(buf, &out->atrb, 0) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s",
|
||||
out->fName);
|
||||
}
|
||||
WFREE(buf, out->heap, DYNTYPE_SFTP);
|
||||
}
|
||||
|
||||
return WS_SUCCESS;
|
||||
|
@ -1055,7 +1118,7 @@ static int wolfSSH_SFTP_SendName(WOLFSSH* ssh, WS_SFTPNAME* list, word32 count,
|
|||
WMEMCPY(out + idx, cur->fName, cur->fSz); idx += cur->fSz;
|
||||
c32toa(cur->lSz, out + idx); idx += UINT32_SZ;
|
||||
WMEMCPY(out + idx, cur->lName, cur->lSz); idx += cur->lSz;
|
||||
if (SFTP_SetAtributes(ssh, out + idx, *outSz - idx, &cur->atrb) !=
|
||||
if (SFTP_SetAttributes(ssh, out + idx, *outSz - idx, &cur->atrb) !=
|
||||
WS_SUCCESS) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
@ -1086,6 +1149,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WS_SFTPNAME* list = NULL;
|
||||
word32 outSz = 0;
|
||||
DIR_HANDLE* cur = dirList;
|
||||
char* dirName = NULL;
|
||||
|
||||
if (ssh == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
@ -1111,6 +1175,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
while (cur != NULL) {
|
||||
if (cur->id == handle) {
|
||||
dir = cur->dir;
|
||||
dirName = cur->dirName;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
|
@ -1127,7 +1192,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
outSz += UINT32_SZ + WOLFSSH_SFTP_HEADER; /* hold header+number of files */
|
||||
do {
|
||||
name = wolfSSH_SFTPNAME_new(ssh->ctx->heap);
|
||||
ret = wolfSSH_SFTPNAME_readdir(ssh, &dir, name);
|
||||
ret = wolfSSH_SFTPNAME_readdir(ssh, &dir, name, dirName);
|
||||
if (ret == WS_SUCCESS || ret == WS_NEXT_ERROR) {
|
||||
count++;
|
||||
outSz += name->fSz + name->lSz + (UINT32_SZ * 2);
|
||||
|
@ -1169,7 +1234,15 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
return WS_FATAL_ERROR;
|
||||
}
|
||||
wolfSSH_SFTPNAME_list_free(list);
|
||||
wolfSSH_stream_send(ssh, data, outSz);
|
||||
|
||||
idx = 0;
|
||||
while (idx < outSz) {
|
||||
if ((ret = wolfSSH_stream_send(ssh, data + idx, outSz - idx)) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
idx += ret;
|
||||
}
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
return WS_SUCCESS;
|
||||
|
@ -1215,6 +1288,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
/* case where node is at head of list */
|
||||
if (pre == cur) {
|
||||
dirList = cur->next;
|
||||
WFREE(cur->dirName, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
}
|
||||
else {
|
||||
|
@ -1225,6 +1299,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
}
|
||||
else {
|
||||
pre->next = cur->next;
|
||||
WFREE(cur->dirName, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
}
|
||||
}
|
||||
|
@ -1232,7 +1307,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
#endif /* NO_WOLFSSH_DIR */
|
||||
|
||||
/* Handles packet to write a file
|
||||
*
|
||||
|
@ -1424,13 +1499,13 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
/* check if is a handle for a directory */
|
||||
if (sz == sizeof(word64)) {
|
||||
ret = wolfSSH_SFTP_RecvCloseDir(ssh, data + idx, sz);
|
||||
}
|
||||
else
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
#endif /* NO_WOLFSSH_DIR */
|
||||
if (sz == sizeof(WFD)) {
|
||||
WMEMSET((byte*)&fd, 0, sizeof(WFD));
|
||||
WMEMCPY((byte*)&fd, data + idx, sz);
|
||||
|
@ -1629,21 +1704,21 @@ int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
* a file descriptor. In those cases we keep track of an internal list matching
|
||||
* handles to file names */
|
||||
|
||||
typedef struct WS_HANDLE_LIST {
|
||||
struct WS_HANDLE_LIST {
|
||||
byte handle[WOLFSSH_MAX_HANDLE];
|
||||
word32 handleSz;
|
||||
char name[WOLFSSH_MAX_FILENAME];
|
||||
struct WS_HANDLE_LIST* next;
|
||||
struct WS_HANDLE_LIST* prev;
|
||||
} WS_HANDLE_LIST;
|
||||
static WS_HANDLE_LIST* handleList = NULL;
|
||||
};
|
||||
|
||||
|
||||
/* get a handle node from the list
|
||||
* returns WS_HANDLE_LIST pointer on success and NULL on failure */
|
||||
static WS_HANDLE_LIST* SFTP_GetHandleNode(byte* handle, word32 handleSz)
|
||||
static WS_HANDLE_LIST* SFTP_GetHandleNode(WOLFSSH* ssh, byte* handle,
|
||||
word32 handleSz)
|
||||
{
|
||||
WS_HANDLE_LIST* cur = handleList;
|
||||
WS_HANDLE_LIST* cur = ssh->handleList;
|
||||
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
|
@ -1690,11 +1765,11 @@ int SFTP_AddHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz, char* name)
|
|||
cur->name[sz] = '\0';
|
||||
|
||||
cur->prev = NULL;
|
||||
cur->next = handleList;
|
||||
if (handleList != NULL) {
|
||||
handleList->prev = cur;
|
||||
cur->next = ssh->handleList;
|
||||
if (ssh->handleList != NULL) {
|
||||
ssh->handleList->prev = cur;
|
||||
}
|
||||
handleList = cur;
|
||||
ssh->handleList = cur;
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
@ -1710,7 +1785,7 @@ int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
cur = SFTP_GetHandleNode(handle, handleSz);
|
||||
cur = SFTP_GetHandleNode(ssh, handle, handleSz);
|
||||
if (cur == NULL) {
|
||||
WLOG(WS_LOG_SFTP, "Fatal Error! Trying to remove a handle that was not in the list");
|
||||
return WS_FATAL_ERROR;
|
||||
|
@ -1725,7 +1800,7 @@ int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
}
|
||||
|
||||
if (cur->next == NULL && cur->prev == NULL) {
|
||||
handleList = NULL;
|
||||
ssh->handleList = NULL;
|
||||
}
|
||||
|
||||
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
|
@ -1770,21 +1845,19 @@ int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr, byte link)
|
|||
|
||||
/* get additional attributes */
|
||||
{
|
||||
byte atrib = 0;
|
||||
if (NU_Get_Attributes(&atrib, fileName) == NU_SUCCESS) {
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if (atrib & ADIRENT) {
|
||||
atr->per |= 0x4000;
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
if (atrib & ANORMAL) {
|
||||
atr->per |= 0x755;
|
||||
}
|
||||
if (atrib & ARDONLY) {
|
||||
atr->per |= 0x444;
|
||||
}
|
||||
byte atrib = stats.fattribute;
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if (atrib & ADIRENT) {
|
||||
atr->per |= 0x41ED; /* 755 with directory */
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
if ((atrib & 0x01) == ANORMAL) {
|
||||
atr->per |= 0x1ED; /* octal 755 */
|
||||
}
|
||||
if (atrib & ARDONLY) {
|
||||
atr->per |= 0x124; /* octal 444 */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1801,7 +1874,8 @@ int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr, byte link)
|
|||
* Fills out a WS_SFTP_FILEATRB structure
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
||||
int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
|
||||
WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
DSTAT stats;
|
||||
WS_HANDLE_LIST* cur;
|
||||
|
@ -1810,7 +1884,7 @@ int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
|||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
cur = SFTP_GetHandleNode(handle, handleSz);
|
||||
cur = SFTP_GetHandleNode(ssh, handle, handleSz);
|
||||
if (cur == NULL) {
|
||||
WLOG(WS_LOG_SFTP, "Unknown handle");
|
||||
return WS_BAD_FILE_E;
|
||||
|
@ -1826,22 +1900,19 @@ int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
|||
atr->sz = (word64)stats.fsize;
|
||||
|
||||
{
|
||||
byte atrib = 0;
|
||||
if (NU_Get_Attributes(&atrib, cur->name) == NU_SUCCESS) {
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if (atrib & ADIRENT) {
|
||||
atr->per |= 0x4000;
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
if (atrib & ANORMAL) {
|
||||
atr->per |= 0x755;
|
||||
}
|
||||
|
||||
if (atrib & ARDONLY) {
|
||||
atr->per |= 0x444;
|
||||
}
|
||||
byte atrib = stats.fattribute;
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if (atrib & ADIRENT) {
|
||||
atr->per |= 0x41ED; /* 755 with directory */
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
if ((atrib & 0x01) == ANORMAL) {
|
||||
atr->per |= 0x1ED; /* octal 755 */
|
||||
}
|
||||
if (atrib & ARDONLY) {
|
||||
atr->per |= 0x124; /* octal 444 */
|
||||
}
|
||||
}
|
||||
/* @TODO handle attribute extensions */
|
||||
|
@ -1902,7 +1973,8 @@ int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr, byte link)
|
|||
* Fills out a WS_SFTP_FILEATRB structure
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
||||
int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
|
||||
WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
|
@ -1935,6 +2007,7 @@ int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
|||
|
||||
/* @TODO handle attribute extensions */
|
||||
|
||||
(void)ssh;
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
@ -1973,7 +2046,7 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
|
||||
/* try to get file attributes and send back to client */
|
||||
WMEMSET((byte*)&atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
if (SFTP_GetAttributes_Handle(handle, handleSz, &atr) != WS_SUCCESS) {
|
||||
if (SFTP_GetAttributes_Handle(ssh, handle, handleSz, &atr) != WS_SUCCESS) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
WLOG(WS_LOG_SFTP, "Unable to get fstat of file/directory");
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_FAILURE, reqId,
|
||||
|
@ -1993,7 +2066,7 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
SFTP_SetAtributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
SFTP_SetAttributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
if (wolfSSH_stream_send(ssh, data, sz + WOLFSSH_SFTP_HEADER) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
|
@ -2067,7 +2140,7 @@ int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
SFTP_SetAtributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
SFTP_SetAttributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
if (wolfSSH_stream_send(ssh, data, sz + WOLFSSH_SFTP_HEADER) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
|
@ -2147,7 +2220,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
SFTP_SetAtributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
SFTP_SetAttributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
if (wolfSSH_stream_send(ssh, data, sz + WOLFSSH_SFTP_HEADER) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
|
@ -2157,6 +2230,125 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Set the files mode
|
||||
* return WS_SUCCESS on success */
|
||||
static int SFTP_SetMode(WOLFSSH* ssh, char* name, word32 mode) {
|
||||
(void)ssh;
|
||||
if (WCHMOD(name, mode) != 0) {
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* sets a files attributes
|
||||
* returns WS_SUCCESS on success */
|
||||
static int SFTP_SetFileAttributes(WOLFSSH* ssh, char* name, 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 */
|
||||
}
|
||||
|
||||
/* check if permissions attribute present */
|
||||
if (atr->flags & WOLFSSH_FILEATRB_PERM) {
|
||||
ret = SFTP_SetMode(ssh, name, atr->per);
|
||||
}
|
||||
|
||||
/* check if time attribute present */
|
||||
if (atr->flags & WOLFSSH_FILEATRB_TIME) {
|
||||
/* @TODO set time */
|
||||
}
|
||||
|
||||
/* 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
|
||||
*/
|
||||
int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
||||
{
|
||||
WS_SFTP_FILEATRB atr;
|
||||
char* name = NULL;
|
||||
int ret;
|
||||
|
||||
word32 sz;
|
||||
byte* data;
|
||||
word32 idx = 0;
|
||||
|
||||
if (ssh == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_SETSTAT");
|
||||
|
||||
data = (byte*)WMALLOC(maxSz, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
if (wolfSSH_stream_read(ssh, data, maxSz) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
if (sz + idx > maxSz) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
/* plus one to make sure is null terminated */
|
||||
name = (char*)WMALLOC(sz + 1, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (name == NULL) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
WMEMCPY(name, data + idx, sz); idx += sz;
|
||||
name[sz] = '\0';
|
||||
clean_path(name);
|
||||
|
||||
if (SFTP_ParseAtributes_buffer(ssh, &atr, data + idx, maxSz - idx) != 0) {
|
||||
printf("error parsing attributes\n");
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_FAILURE, reqId,
|
||||
"Unable to parse attributes error", "English");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
/* try to set file attributes and send status back to client */
|
||||
if ((ret = SFTP_SetFileAttributes(ssh, name, &atr))
|
||||
!= WS_SUCCESS) {
|
||||
WFREE(name, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
/* tell peer that was not ok */
|
||||
WLOG(WS_LOG_SFTP, "Unable to get set attributes of file/directory");
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_FAILURE, reqId,
|
||||
"Unable to set attributes error", "English");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
WFREE(name, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_OK, reqId, "Set Attirbutes",
|
||||
"English");
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif /* !NO_WOLFSSH_SERVER */
|
||||
|
||||
|
||||
|
@ -2402,7 +2594,7 @@ static int wolfSSH_SFTP_DoStatus(WOLFSSH* ssh, word32 reqId)
|
|||
}
|
||||
ato32(buf, &sz);
|
||||
|
||||
{
|
||||
if (sz > 0) {
|
||||
byte* s = (byte*)WMALLOC(sz + 1, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (s == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
|
@ -2426,8 +2618,7 @@ static int wolfSSH_SFTP_DoStatus(WOLFSSH* ssh, word32 reqId)
|
|||
}
|
||||
ato32(buf, &sz);
|
||||
|
||||
if (sz > 0)
|
||||
{
|
||||
if (sz > 0) {
|
||||
byte* s = (byte*)WMALLOC(sz + 1, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (s == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
|
@ -2498,6 +2689,7 @@ int SFTP_ParseAtributes_buffer(WOLFSSH* ssh, WS_SFTP_FILEATRB* atr, byte* buf,
|
|||
word32 idx = 0;
|
||||
|
||||
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
|
||||
/* get flags */
|
||||
ato32(buf, &atr->flags); idx += UINT32_SZ;
|
||||
|
||||
|
@ -2749,7 +2941,7 @@ static WS_SFTPNAME* wolfSSH_SFTP_DoName(WOLFSSH* ssh)
|
|||
ato32(buf, &sz);
|
||||
tmp->fSz = sz;
|
||||
if (sz > 0) {
|
||||
tmp->fName = (char*)XMALLOC(sz + 1, tmp->heap, DYNTYPE_SFTP);
|
||||
tmp->fName = (char*)WMALLOC(sz + 1, tmp->heap, DYNTYPE_SFTP);
|
||||
if (tmp->fName == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
break;
|
||||
|
@ -2772,7 +2964,7 @@ static WS_SFTPNAME* wolfSSH_SFTP_DoName(WOLFSSH* ssh)
|
|||
ato32(buf, &sz);
|
||||
tmp->lSz = sz;
|
||||
if (sz > 0) {
|
||||
tmp->lName = (char*)XMALLOC(sz + 1, tmp->heap, DYNTYPE_SFTP);
|
||||
tmp->lName = (char*)WMALLOC(sz + 1, tmp->heap, DYNTYPE_SFTP);
|
||||
if (tmp->lName == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
break;
|
||||
|
@ -2914,6 +3106,37 @@ WS_SFTPNAME* wolfSSH_SFTP_LS(WOLFSSH* ssh, char* dir)
|
|||
}
|
||||
|
||||
|
||||
/* Takes in an octal file permissions value and sets it to the file/directory
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
int wolfSSH_SFTP_CHMOD(WOLFSSH* ssh, char* n, char* oct)
|
||||
{
|
||||
int ret;
|
||||
int mode;
|
||||
WS_SFTP_FILEATRB atr;
|
||||
|
||||
if (ssh == NULL || n == NULL || oct == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
/* convert from octal to decimal */
|
||||
mode = wolfSSH_oct2dec(ssh, (byte*)oct, (word32)WSTRLEN(oct));
|
||||
if (mode < 0) {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/* get current attributes of path */
|
||||
WMEMSET(&atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
if ((ret = wolfSSH_SFTP_STAT(ssh, n, &atr)) != WS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* update permissions */
|
||||
atr.per = mode;
|
||||
return wolfSSH_SFTP_SetSTAT(ssh, n, &atr);
|
||||
}
|
||||
|
||||
|
||||
/* helper function for common code between LSTAT and STAT
|
||||
*
|
||||
* returns WS_SUCCESS on success
|
||||
|
@ -2997,6 +3220,69 @@ int wolfSSH_SFTP_LSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
|||
}
|
||||
|
||||
|
||||
/* Sends packet to set the attributes of path
|
||||
*
|
||||
* dir NULL terminated string of path
|
||||
* atr structure holding file attributes to use
|
||||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
int wolfSSH_SFTP_SetSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
int dirSz, atrSz, status;
|
||||
word32 maxSz, reqId;
|
||||
byte type;
|
||||
byte* data;
|
||||
word32 idx;
|
||||
|
||||
WLOG(WS_LOG_SFTP, "Entering wolfSSH_SFTP_SetSTAT()");
|
||||
if (ssh == NULL || dir == NULL || atr == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
dirSz = (int)WSTRLEN(dir);
|
||||
atrSz = SFTP_AtributesSz(ssh, atr);
|
||||
data = (byte*)WMALLOC(dirSz + atrSz + WOLFSSH_SFTP_HEADER + UINT32_SZ,
|
||||
ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
if (SFTP_SetHeader(ssh, ssh->reqId, WOLFSSH_FTP_SETSTAT,
|
||||
dirSz + atrSz + UINT32_SZ, data) != WS_SUCCESS) {
|
||||
WFREE(data, NULL, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
idx = WOLFSSH_SFTP_HEADER;
|
||||
c32toa(dirSz, data + idx); idx += UINT32_SZ;
|
||||
WMEMCPY(data + idx, (byte*)dir, dirSz); idx += dirSz;
|
||||
SFTP_SetAttributes(ssh, data + idx, atrSz, atr); idx += atrSz;
|
||||
|
||||
/* send header and type specific data */
|
||||
if (wolfSSH_stream_send(ssh, data, idx) < 0) {
|
||||
WFREE(data, NULL, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
WFREE(data, NULL, DYNTYPE_BUFFER);
|
||||
|
||||
maxSz = SFTP_GetHeader(ssh, &reqId, &type);
|
||||
if (type != WOLFSSH_FTP_STATUS) {
|
||||
WLOG(WS_LOG_SFTP, "Unexpected packet type %d", type);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
else {
|
||||
status = wolfSSH_SFTP_DoStatus(ssh, reqId);
|
||||
if (status != WOLFSSH_FTP_OK) {
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
}
|
||||
(void)maxSz;
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Open a file for reading/writing
|
||||
*
|
||||
* dir NULL terminated string holding file name
|
||||
|
@ -3909,4 +4195,28 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* called when wolfSSH_free() is called
|
||||
* return WS_SUCCESS on success */
|
||||
int wolfSSH_SFTP_free(WOLFSSH* ssh)
|
||||
{
|
||||
(void)ssh;
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
{
|
||||
WS_HANDLE_LIST* cur = ssh->handleList;
|
||||
|
||||
/* go through and free handles and make sure files are closed */
|
||||
while (cur != NULL) {
|
||||
WCLOSE(*((WFD*)cur->handle));
|
||||
if (SFTP_RemoveHandleNode(ssh, cur->handle, cur->handleSz)
|
||||
!= WS_SUCCESS) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
cur = ssh->handleList;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSH_SFTP */
|
||||
|
|
|
@ -204,6 +204,7 @@ static void ShowCommands(void)
|
|||
{
|
||||
printf("\n\nCommands :\n");
|
||||
printf("\tcd <string> change directory\n");
|
||||
printf("\tchmod <mode> <path> change mode\n");
|
||||
printf("\tget <remote file> <local file> pulls file(s) from server\n");
|
||||
printf("\tls list current directory\n");
|
||||
printf("\tmkdir <dir name> creates new directory on server\n");
|
||||
|
@ -534,6 +535,61 @@ int doCmds()
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((pt = WSTRNSTR(msg, "chmod", sizeof(msg))) != NULL) {
|
||||
int sz;
|
||||
char* f = NULL;
|
||||
char mode[WOLFSSH_MAX_OCTET_LEN];
|
||||
|
||||
pt += sizeof("chmod");
|
||||
sz = (int)WSTRLEN(pt);
|
||||
|
||||
if (pt[sz - 1] == '\n') pt[sz - 1] = '\0';
|
||||
|
||||
/* get mode */
|
||||
sz = (sz < WOLFSSH_MAX_OCTET_LEN - 1)? sz :
|
||||
WOLFSSH_MAX_OCTET_LEN -1;
|
||||
WMEMCPY(mode, pt, sz);
|
||||
mode[WOLFSSH_MAX_OCTET_LEN - 1] = '\0';
|
||||
for (i = sz; i > 0; i--) {
|
||||
if (mode[i] == ' ') {
|
||||
mode[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 0) {
|
||||
printf("error with getting mode\r\n");
|
||||
continue;
|
||||
}
|
||||
pt += (int)WSTRLEN(mode);
|
||||
sz = (int)WSTRLEN(pt);
|
||||
for (i = 0; i < sz && pt[0] == ' '; i++, pt++);
|
||||
|
||||
if (pt[0] != '/') {
|
||||
int maxSz = (int)WSTRLEN(workingDir) + sz + 2;
|
||||
f = XMALLOC(maxSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (f == NULL) {
|
||||
err_sys("Error malloc'ing");
|
||||
}
|
||||
|
||||
f[0] = '\0';
|
||||
WSTRNCAT(f, workingDir, maxSz);
|
||||
if (WSTRLEN(workingDir) > 1) {
|
||||
WSTRNCAT(f, "/", maxSz);
|
||||
}
|
||||
WSTRNCAT(f, pt, maxSz);
|
||||
|
||||
pt = f;
|
||||
}
|
||||
|
||||
/* update permissions */
|
||||
if (wolfSSH_SFTP_CHMOD(ssh, pt, mode) != WS_SUCCESS) {
|
||||
printf("unable to change path permissions\n");
|
||||
}
|
||||
|
||||
XFREE(f, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pt = WSTRNSTR(msg, "rmdir", sizeof(msg))) != NULL) {
|
||||
int sz;
|
||||
char* f = NULL;
|
||||
|
|
|
@ -245,6 +245,7 @@ typedef struct HandshakeInfo {
|
|||
#ifdef WOLFSSH_SFTP
|
||||
#define WOLFSSH_MAX_SFTPOFST 3
|
||||
|
||||
typedef struct WS_HANDLE_LIST WS_HANDLE_LIST;
|
||||
typedef struct SFTP_OFST {
|
||||
word64 offset;
|
||||
char from[WOLFSSH_MAX_FILENAME];
|
||||
|
@ -312,7 +313,6 @@ struct WOLFSSH {
|
|||
ScpSendCtx scpSendCbCtx; /* used in default case to for send cb ctx */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
byte connReset;
|
||||
byte isClosed;
|
||||
byte clientOpenSSH;
|
||||
|
@ -369,6 +369,9 @@ struct WOLFSSH {
|
|||
byte sftpState;
|
||||
byte sftpInt;
|
||||
SFTP_OFST sftpOfst[WOLFSSH_MAX_SFTPOFST];
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
WS_HANDLE_LIST* handleList;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -662,6 +665,7 @@ WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH*, int, const char*, char*, word32,
|
|||
|
||||
WOLFSSH_LOCAL void clean_path(char* path);
|
||||
WOLFSSH_LOCAL void DumpOctetString(const byte*, word32);
|
||||
WOLFSSH_LOCAL int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -89,6 +89,35 @@ extern "C" {
|
|||
|
||||
#define WCLOSE(fd) NU_Close((fd))
|
||||
|
||||
static inline int wChmod(const char* f, int mode) {
|
||||
unsigned char atr = 0;
|
||||
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NU_Get_Attributes(&atr, f) != NU_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set attribute value */
|
||||
atr = atr & 0xF0; /* clear first byte */
|
||||
if (mode == 0x124) {
|
||||
atr |= ARDONLY; /* set read only value */
|
||||
}
|
||||
else {
|
||||
/* if not setting read only set to normal */
|
||||
atr |= ANORMAL;
|
||||
}
|
||||
|
||||
if (NU_Set_Attributes(f, atr) != NU_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#define WCHMOD(f,m) wChmod((f),(m))
|
||||
#else
|
||||
#define WFILE FILE
|
||||
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
|
||||
|
@ -102,6 +131,7 @@ extern "C" {
|
|||
#define WREWIND(s) rewind((s))
|
||||
#define WSEEK_END SEEK_END
|
||||
#define WUTIMES(f,t) utimes((f),(t))
|
||||
#define WCHMOD(f,m) chmod((f),(m))
|
||||
|
||||
#if (defined(WOLFSSH_SCP) || defined(WOLFSSH_SFTP)) && \
|
||||
!defined(WOLFSSH_SCP_USER_CALLBACKS) && \
|
||||
|
@ -247,7 +277,7 @@ extern "C" {
|
|||
}
|
||||
#define WUTIMES(f,t) wUtimes((f), (t))
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
#define WDIR DSTAT
|
||||
|
||||
#ifndef WOPENDIR
|
||||
|
@ -310,7 +340,7 @@ extern "C" {
|
|||
|
||||
#define WCLOSEDIR(d) NU_Done((d))
|
||||
#define WREADDIR(d) (NU_Get_Next((d)) == NU_SUCCESS)?(d):NULL
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
#endif /* NO_WOLFSSH_DIR */
|
||||
#else
|
||||
#include <unistd.h> /* used for rmdir */
|
||||
#include <sys/stat.h> /* used for mkdir, stat, and lstat */
|
||||
|
@ -340,7 +370,7 @@ extern "C" {
|
|||
#define WPWRITE(fd,b,s,o) pwrite((fd),(b),(s),(o))
|
||||
#define WPREAD(fd,b,s,o) pread((fd),(b),(s),(o))
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
#include <dirent.h> /* used for opendir, readdir, and closedir */
|
||||
#define WDIR DIR*
|
||||
|
||||
|
@ -348,7 +378,7 @@ extern "C" {
|
|||
#define WOPENDIR(c,d) ((*(c) = opendir((d))) == NULL)
|
||||
#define WCLOSEDIR(d) closedir(*(d))
|
||||
#define WREADDIR(d) readdir(*(d))
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
#endif /* NO_WOLFSSH_DIR */
|
||||
#endif
|
||||
#endif /* WOLFSSH_SFTP or WOLFSSH_SCP */
|
||||
|
||||
|
|
|
@ -220,6 +220,7 @@ enum WS_DisconnectReasonCodes {
|
|||
#ifndef WOLFSSH_MAX_FILENAME
|
||||
#define WOLFSSH_MAX_FILENAME 256
|
||||
#endif
|
||||
#define WOLFSSH_MAX_OCTET_LEN 6
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -169,6 +169,7 @@ WOLFSSH_API int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle,
|
|||
word32 handleSz, word64 ofst, byte* out, word32 outSz);
|
||||
WOLFSSH_API int wolfSSH_SFTP_STAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr);
|
||||
WOLFSSH_API int wolfSSH_SFTP_LSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr);
|
||||
WOLFSSH_API int wolfSSH_SFTP_SetSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr);
|
||||
|
||||
WOLFSSH_API void wolfSSH_SFTPNAME_free(WS_SFTPNAME* n);
|
||||
WOLFSSH_API void wolfSSH_SFTPNAME_list_free(WS_SFTPNAME* n);
|
||||
|
@ -190,6 +191,7 @@ WOLFSSH_API int wolfSSH_SFTP_RMDIR(WOLFSSH* ssh, char* dir);
|
|||
WOLFSSH_API int wolfSSH_SFTP_Rename(WOLFSSH* ssh, const char* old,
|
||||
const char* nw);
|
||||
WOLFSSH_API WS_SFTPNAME* wolfSSH_SFTP_LS(WOLFSSH* ssh, char* dir);
|
||||
WOLFSSH_API int wolfSSH_SFTP_CHMOD(WOLFSSH* ssh, char* n, char* oct);
|
||||
|
||||
typedef void(WS_STATUS_CB)(WOLFSSH*, long, char*);
|
||||
WOLFSSH_API int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, char* to,
|
||||
|
@ -215,14 +217,16 @@ WOLFSSH_LOCAL int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle,
|
||||
word32 handleSz);
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
#endif /* NO_WOLFSSH_DIR */
|
||||
|
||||
WOLFSSL_LOCAL int wolfSSH_SFTP_free(WOLFSSH* ssh);
|
||||
WOLFSSL_LOCAL int SFTP_AddHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz, char* name);
|
||||
WOLFSSL_LOCAL int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz);
|
||||
|
|
Loading…
Reference in New Issue