1+ /* myFilesystem.c
2+ *
3+ * Copyright (C) 2014-2025 wolfSSL Inc.
4+ *
5+ *
6+ * wolfSSH is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; either version 3 of the License, or
9+ * (at your option) any later version.
10+ *
11+ * wolfSSH is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+ #include "myFilesystem.h"
21+ #include <wolfssh/ssh.h>
22+ #include <wolfssh/wolfsftp.h>
23+ #include <wolfssh/log.h>
24+ #include <stdlib.h>
25+ #include <stdio.h>
26+ #include "system/fs/sys_fs.h"
27+
28+ #ifdef WOLFSSH_USER_FILESYSTEM
29+ /*******************************************************************************
30+ Restricted function implementations
31+ *******************************************************************************/
32+
33+ /* helper function to check if the user is allowed to do an operation */
34+ static int isUserAllowed (void * fs )
35+ {
36+ char * currentUser ;
37+ WOLFSSH * ssh = (WOLFSSH * )fs ;
38+
39+ if (ssh == NULL ) {
40+ return 0 ;
41+ }
42+
43+ currentUser = wolfSSH_GetUsername (ssh );
44+ if (currentUser && XSTRCMP (currentUser , "admin" ) == 0 ) {
45+ return 1 ;
46+ }
47+ return 0 ;
48+ }
49+
50+
51+ int wFwrite (void * fs , unsigned char * b , int s , int a , WFILE * f )
52+ {
53+ if (isUserAllowed (fs )) {
54+ return SYS_FS_FileWrite (* f , b , s * a );
55+ }
56+ else {
57+ return -1 ;
58+ }
59+ }
60+
61+
62+ int wChmod (void * fs , const char * path , int mode )
63+ {
64+ SYS_FS_RESULT ret ;
65+ SYS_FS_FILE_DIR_ATTR attr = 0 ;
66+
67+ if (isUserAllowed (fs )) {
68+ /* mode is the octal value i.e 666 is 0x1B6 */
69+ if ((mode & 0x180 ) != 0x180 ) { /* not octal 6XX read only */
70+ attr |= SYS_FS_ATTR_RDO ;
71+ }
72+
73+ /* toggle the read only attribute */
74+ ret = SYS_FS_FileDirectoryModeSet (path , attr , SYS_FS_ATTR_RDO );
75+ if (ret != SYS_FS_RES_SUCCESS ) {
76+ return -1 ;
77+ }
78+ return 0 ;
79+ }
80+ else {
81+ return -1 ;
82+ }
83+ }
84+
85+
86+ int wPwrite (void * fs , WFD fd , unsigned char * buf , unsigned int sz ,
87+ const unsigned int * shortOffset )
88+ {
89+ int ret = -1 ;
90+
91+ if (isUserAllowed (fs )) {
92+ ret = (int )WFSEEK (NULL , & fd , shortOffset [0 ], SYS_FS_SEEK_SET );
93+ if (ret != -1 ) {
94+ ret = (int )WFWRITE (NULL , buf , 1 , sz , & fd );
95+ }
96+ }
97+
98+ return ret ;
99+ }
100+
101+ int wMkdir (void * fs , unsigned char * path )
102+ {
103+ if (isUserAllowed (fs )) {
104+ return SYS_FS_DirectoryMake (path );
105+ }
106+ else {
107+ return -1 ;
108+ }
109+ }
110+
111+
112+ int wRmdir (void * fs , unsigned char * dir )
113+ {
114+ if (isUserAllowed (fs )) {
115+ return SYS_FS_FileDirectoryRemove (dir );
116+ }
117+ else {
118+ return -1 ;
119+ }
120+ }
121+
122+ int wRemove (void * fs , unsigned char * dir )
123+ {
124+ if (isUserAllowed (fs )) {
125+ return SYS_FS_FileDirectoryRemove (dir );
126+ }
127+ else {
128+ return -1 ;
129+ }
130+ }
131+
132+
133+ int wRename (void * fs , unsigned char * orig , unsigned char * newName )
134+ {
135+ if (isUserAllowed (fs )) {
136+ return SYS_FS_FileDirectoryRenameMove (orig , newName );
137+ }
138+ else {
139+ return -1 ;
140+ }
141+ }
142+
143+
144+ /*******************************************************************************
145+ "SAFE" function implementations any user is ok
146+ *******************************************************************************/
147+ int wDirOpen (void * heap , WDIR * dir , const char * path )
148+ {
149+ * dir = SYS_FS_DirOpen (path );
150+ if (* dir == SYS_FS_HANDLE_INVALID ) {
151+ return -1 ;
152+ }
153+ return 0 ;
154+ }
155+
156+ int wStat (const char * path , WSTAT_T * stat )
157+ {
158+ int ret ;
159+
160+ WMEMSET (stat , 0 , sizeof (WSTAT_T ));
161+ ret = SYS_FS_FileStat (path , stat );
162+
163+ if (ret != SYS_FS_RES_SUCCESS ) {
164+ WLOG (WS_LOG_SFTP ,
165+ "Return from SYS_FS_fileStat [%s] = %d, expecting %d" ,
166+ path , ret , SYS_FS_RES_SUCCESS );
167+ WLOG (WS_LOG_SFTP , "SYS error reason = %d" , SYS_FS_Error ());
168+ return -1 ;
169+ }
170+ else {
171+ return 0 ;
172+ }
173+ return 0 ;
174+ }
175+
176+ char * wGetCwd (char * r , int rSz )
177+ {
178+ SYS_FS_RESULT ret ;
179+ ret = SYS_FS_CurrentWorkingDirectoryGet (r , rSz );
180+ if (ret != SYS_FS_RES_SUCCESS ) {
181+ return r ;
182+ }
183+ return r ;
184+ }
185+
186+
187+ int wfopen (WFILE * f , const char * filename , SYS_FS_FILE_OPEN_ATTRIBUTES mode )
188+ {
189+ if (f != NULL ) {
190+ * f = SYS_FS_FileOpen (filename , mode );
191+ if (* f == WBADFILE ) {
192+ WLOG (WS_LOG_SFTP , "Failed to open file %s" , filename );
193+ return 1 ;
194+ }
195+ else {
196+ WLOG (WS_LOG_SFTP , "Opened file %s" , filename );
197+ return 0 ;
198+ }
199+ }
200+ return 1 ;
201+ }
202+
203+
204+ int wPread (WFD fd , unsigned char * buf , unsigned int sz ,
205+ const unsigned int * shortOffset )
206+ {
207+ int ret ;
208+
209+ ret = (int )WFSEEK (NULL , & fd , shortOffset [0 ], SYS_FS_SEEK_SET );
210+ if (ret != -1 )
211+ ret = (int )WFREAD (NULL , buf , 1 , sz , & fd );
212+
213+ return ret ;
214+ }
215+
216+
217+ /*******************************************************************************
218+ File attribute functions
219+ *******************************************************************************/
220+
221+ typedef struct WS_HANDLE_LIST {
222+ byte handle [WOLFSSH_MAX_HANDLE ];
223+ word32 handleSz ;
224+ char name [WOLFSSH_MAX_FILENAME ];
225+ struct WS_HANDLE_LIST * next ;
226+ struct WS_HANDLE_LIST * prev ;
227+ } WS_HANDLE_LIST ;
228+
229+ int SFTP_GetAttributesStat (void * atrIn , void * statsIn )
230+ {
231+ WS_SFTP_FILEATRB * atr = (WS_SFTP_FILEATRB * )atrIn ;
232+ WSTAT_T * stats = (WSTAT_T * )statsIn ;
233+ /* file size */
234+ atr -> flags |= WOLFSSH_FILEATRB_SIZE ;
235+ atr -> sz [0 ] = (word32 )stats -> fsize ;
236+ atr -> sz [1 ] = (word32 )(0 );
237+
238+ /* file permissions */
239+ atr -> flags |= WOLFSSH_FILEATRB_PERM ;
240+ if ((stats -> fattrib & SYS_FS_ATTR_DIR ) & SYS_FS_ATTR_MASK ) {
241+ atr -> per |= 0x41ED ; /* 755 with directory */
242+ }
243+ else {
244+ atr -> per |= 0x8000 ;
245+ }
246+
247+ /* check for read only */
248+ if ((stats -> fattrib & SYS_FS_ATTR_RDO ) & SYS_FS_ATTR_MASK ) {
249+ atr -> per |= 0x124 ; /* octal 444 */
250+ }
251+ else {
252+ atr -> per |= 0x1ED ; /* octal 755 */
253+ }
254+
255+ /* last modified time */
256+ atr -> mtime = stats -> ftime ;
257+
258+ return WS_SUCCESS ;
259+ }
260+
261+
262+ static int SFTP_GetAttributesHelper (WS_SFTP_FILEATRB * atr , const char * fName )
263+ {
264+ WSTAT_T stats ;
265+ SYS_FS_RESULT res ;
266+ char buffer [255 ];
267+
268+ WMEMSET (atr , 0 , sizeof (WS_SFTP_FILEATRB ));
269+ WMEMSET (buffer , 0 , sizeof (buffer ));
270+ res = SYS_FS_CurrentDriveGet (buffer );
271+ if (res == SYS_FS_RES_SUCCESS ) {
272+ if (WSTRCMP (fName , buffer ) == 0 ) {
273+ atr -> flags |= WOLFSSH_FILEATRB_PERM ;
274+ atr -> per |= 0x41ED ; /* 755 with directory */
275+ atr -> per |= 0x1ED ; /* octal 755 */
276+
277+ atr -> flags |= WOLFSSH_FILEATRB_SIZE ;
278+ atr -> sz [0 ] = 0 ;
279+ atr -> sz [1 ] = 0 ;
280+
281+ atr -> mtime = 30912 ;
282+ WLOG (WS_LOG_SFTP , "Setting mount point as directory" );
283+ return WS_SUCCESS ;
284+ }
285+ }
286+
287+ if (WSTAT (ssh -> fs , fName , & stats ) != 0 ) {
288+ WLOG (WS_LOG_SFTP , "Issue with WSTAT call" );
289+ return WS_BAD_FILE_E ;
290+ }
291+ return SFTP_GetAttributesStat (atr , & stats );
292+ }
293+
294+
295+ /* NOTE: if atr->flags is set to a value of 0 then no attributes are set.
296+ * Fills out a WS_SFTP_FILEATRB structure
297+ * returns WS_SUCCESS on success
298+ */
299+ int SFTP_GetAttributes (void * fs , const char * fileName , void * atr ,
300+ byte noFollow , void * heap )
301+ {
302+ WOLFSSH_UNUSED (heap );
303+ WOLFSSH_UNUSED (fs );
304+
305+ return SFTP_GetAttributesHelper ((WS_SFTP_FILEATRB * )atr , fileName );
306+ }
307+
308+
309+ /* Gets attributes based on file descriptor
310+ * NOTE: if atr->flags is set to a value of 0 then no attributes are set.
311+ * Fills out a WS_SFTP_FILEATRB structure
312+ * returns WS_SUCCESS on success
313+ */
314+ int SFTP_GetAttributes_Handle (void * ssh , unsigned char * handle , int handleSz ,
315+ char * name , void * atr )
316+ {
317+ return SFTP_GetAttributesHelper ((WS_SFTP_FILEATRB * )atr , name );
318+ }
319+ #endif /* WOLFSSH_USER_FILESYSTEM */
0 commit comments