sftp_server_packet.c
Go to the documentation of this file.
1 /**
2  * @file sftp_server_packet.c
3  * @brief SFTP packet parsing and formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSH Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL SFTP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ssh/ssh_misc.h"
36 #include "sftp/sftp_server.h"
37 #include "sftp/sftp_server_file.h"
40 #include "sftp/sftp_server_misc.h"
41 #include "path.h"
42 #include "debug.h"
43 
44 //Check SSH stack configuration
45 #if (SFTP_SERVER_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Parse SSH_FXP_INIT packet
50  * @param[in] session Handle referencing an SFTP session
51  * @param[in] packet Pointer to packet
52  * @param[in] length Length of the packet, in bytes
53  * @return Error code
54  **/
55 
57  const uint8_t *packet, size_t length)
58 {
59  error_t error;
60  uint32_t version;
61 
62  //Debug message
63  TRACE_INFO("SSH_FXP_INIT packet received (%" PRIuSIZE " bytes)...\r\n", length);
64  TRACE_VERBOSE_ARRAY(" ", packet, length);
65 
66  //Malformed packet?
67  if(length != sizeof(uint32_t))
68  return ERROR_INVALID_PACKET;
69 
70  //The SSH_FXP_INIT packet contains the client version
71  version = LOAD32BE(packet);
72 
73  //Sanity check
75  return ERROR_INVALID_VERSION;
76 
77  //The server responds with an SSH_FXP_VERSION packet, supplying the lowest
78  //of its own and the client's version number. Both parties should from then
79  //on adhere to particular version of the protocol
80  session->version = (SftpVersion) MIN(version, SFTP_SERVER_MAX_VERSION);
81 
82  //Send an SSH_FXP_VERSION packet to the client
83  error = sftpFormatFxpVersion(session, session->version);
84 
85  //Return status code
86  return error;
87 }
88 
89 
90 /**
91  * @brief Parse SSH_FXP_OPEN packet
92  * @param[in] session Handle referencing an SFTP session
93  * @param[in] packet Pointer to packet
94  * @param[in] length Length of the packet, in bytes
95  * @return Error code
96  **/
97 
99  const uint8_t *packet, size_t length)
100 {
101  error_t error;
102  size_t n;
103  uint32_t id;
104  uint32_t pflags;
105  uint32_t handle;
106  const uint8_t *p;
109 
110  //Debug message
111  TRACE_INFO("SSH_FXP_OPEN packet received (%" PRIuSIZE " bytes)...\r\n", length);
112  TRACE_VERBOSE_ARRAY(" ", packet, length);
113 
114  //Point to the first field of the packet
115  p = packet;
116 
117  //Malformed packet?
118  if(length < sizeof(uint32_t))
119  return ERROR_INVALID_PACKET;
120 
121  //Get request identifier
122  id = LOAD32BE(p);
123 
124  //Point to the next field
125  p += sizeof(uint32_t);
126  length -= sizeof(uint32_t);
127 
128  //Get filename
129  error = sshParseString(p, length, &filename);
130  //Any error to report?
131  if(error)
132  return error;
133 
134  //Point to the next field
135  p += sizeof(uint32_t) + filename.length;
136  length -= sizeof(uint32_t) + filename.length;
137 
138  //Malformed packet?
139  if(length < sizeof(uint32_t))
140  return ERROR_INVALID_PACKET;
141 
142  //Get pflags
143  pflags = LOAD32BE(p);
144 
145  //Point to the next field
146  p += sizeof(uint32_t);
147  length -= sizeof(uint32_t);
148 
149  //Parse ATTRS compound data
150  error = sftpParseAttributes(session->version, &attributes, p, length, &n);
151  //Any error to report?
152  if(error)
153  return error;
154 
155  //Malformed packet?
156  if(length != n)
157  return ERROR_INVALID_PACKET;
158 
159  //Open the specified file
160  error = sftpServerOpenFile(session, &filename, pflags, &attributes,
161  &handle);
162 
163  //Check status code
164  if(error == NO_ERROR)
165  {
166  //The server will respond to this request with an SSH_FXP_HANDLE packet
167  error = sftpFormatFxpHandle(session, id, handle);
168  }
169  else if(error == ERROR_OUT_OF_RESOURCES)
170  {
171  //Too many files have been open
172  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
173  "Too many open files");
174  }
175  else if(error == ERROR_ACCESS_DENIED)
176  {
177  //The authenticated user does not have sufficient permissions to perform
178  //the operation
179  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
180  "Permission denied");
181  }
182  else
183  {
184  //The specified path name does not exist
185  error = sftpFormatFxpStatus(session, id, SSH_FX_NO_SUCH_FILE,
186  "No such file");
187  }
188 
189  //Return status code
190  return error;
191 }
192 
193 
194 /**
195  * @brief Parse SSH_FXP_CLOSE packet
196  * @param[in] session Handle referencing an SFTP session
197  * @param[in] packet Pointer to packet
198  * @param[in] length Length of the packet, in bytes
199  * @return Error code
200  **/
201 
203  const uint8_t *packet, size_t length)
204 {
205  error_t error;
206  uint32_t id;
207  const uint8_t *p;
208  SshBinaryString handle;
209 
210  //Debug message
211  TRACE_INFO("SSH_FXP_CLOSE packet received (%" PRIuSIZE " bytes)...\r\n", length);
212  TRACE_VERBOSE_ARRAY(" ", packet, length);
213 
214  //Point to the first field of the packet
215  p = packet;
216 
217  //Malformed packet?
218  if(length < sizeof(uint32_t))
219  return ERROR_INVALID_PACKET;
220 
221  //Get request identifier
222  id = LOAD32BE(p);
223 
224  //Point to the next field
225  p += sizeof(uint32_t);
226  length -= sizeof(uint32_t);
227 
228  //Get handle
229  error = sshParseBinaryString(p, length, &handle);
230  //Any error to report?
231  if(error)
232  return error;
233 
234  //Malformed message?
235  if(length != (sizeof(uint32_t) + handle.length))
236  return ERROR_INVALID_PACKET;
237 
238  //An SSH_FXP_CLOSE request can be used to close a file
239  error = sftpServerCloseFile(session, &handle);
240 
241  //Check status code
242  if(error)
243  {
244  //This request can also be used to close a directory
245  error = sftpServerCloseDir(session, &handle);
246  }
247 
248  //Check status code
249  if(!error)
250  {
251  //When the operation is successful, the server responds with an
252  //SSH_FXP_STATUS message with SSH_FX_OK status
253  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
254  }
255  else
256  {
257  //If an error occurs, the server responds with an SSH_FXP_STATUS
258  //message message indicating an failure
259  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
260  "Invalid handle");
261  }
262 
263  //Return status code
264  return error;
265 }
266 
267 
268 /**
269  * @brief Parse SSH_FXP_READ packet
270  * @param[in] session Handle referencing an SFTP session
271  * @param[in] packet Pointer to packet
272  * @param[in] length Length of the packet, in bytes
273  * @return Error code
274  **/
275 
277  const uint8_t *packet, size_t length)
278 {
279  error_t error;
280  uint32_t id;
281  uint32_t dataLen;
282  uint64_t offset;
283  const uint8_t *p;
284  SshBinaryString handle;
285 
286  //Debug message
287  TRACE_DEBUG("SSH_FXP_READ packet received (%" PRIuSIZE " bytes)...\r\n", length);
288  TRACE_VERBOSE_ARRAY(" ", packet, length);
289 
290  //Point to the first field of the packet
291  p = packet;
292 
293  //Malformed packet?
294  if(length < sizeof(uint32_t))
295  return ERROR_INVALID_PACKET;
296 
297  //Get request identifier
298  id = LOAD32BE(p);
299 
300  //Point to the next field
301  p += sizeof(uint32_t);
302  length -= sizeof(uint32_t);
303 
304  //Get handle
305  error = sshParseBinaryString(p, length, &handle);
306  //Any error to report?
307  if(error)
308  return error;
309 
310  //Point to the next field
311  p += sizeof(uint32_t) + handle.length;
312  length -= sizeof(uint32_t) + handle.length;
313 
314  //Malformed packet?
315  if(length < sizeof(uint64_t))
316  return ERROR_INVALID_PACKET;
317 
318  //The 'offset' field is the offset is relative to the beginning of the
319  //file from where to start reading
320  offset = LOAD64BE(p);
321 
322  //Point to the next field
323  p += sizeof(uint64_t);
324  length -= sizeof(uint64_t);
325 
326  //Malformed packet?
327  if(length != sizeof(uint32_t))
328  return ERROR_INVALID_PACKET;
329 
330  //The 'len' field is the maximum number of bytes to read
331  dataLen = LOAD32BE(p);
332 
333  //Read data from the specified file
334  error = sftpServerReadFile(session, &handle, offset, &dataLen);
335 
336  //Check status code
337  if(!error)
338  {
339  //In response to this request, the server will read as many bytes as it
340  //can from the file (up to 'len'), and return them in an SSH_FXP_DATA
341  //message
342  error = sftpFormatFxpData(session, id, dataLen);
343  }
344 
345  //Check status code
346  if(error == NO_ERROR)
347  {
348  //Successful read operation
349  }
350  else if(error == ERROR_END_OF_STREAM)
351  {
352  //End-of-file condition
353  error = sftpFormatFxpStatus(session, id, SSH_FX_EOF, "No more data");
354  }
355  else if(error == ERROR_INVALID_HANDLE)
356  {
357  //The supplied handle is not valid
358  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
359  "Invalid handle");
360  }
361  else
362  {
363  //Generic error
364  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
365  "Failed to read data");
366  }
367 
368  //Return status code
369  return error;
370 }
371 
372 
373 /**
374  * @brief Parse SSH_FXP_WRITE packet
375  * @param[in] session Handle referencing an SFTP session
376  * @param[in] packet Pointer to packet
377  * @param[in] fragLen Number of bytes available on hand
378  * @param[in] totalLen Total length of the packet, in bytes
379  * @return Error code
380  **/
381 
383  const uint8_t *packet, size_t fragLen, size_t totalLen)
384 {
385  error_t error;
386  uint64_t offset;
387  const uint8_t *p;
388  SshBinaryString handle;
390 
391  //Debug message
392  TRACE_DEBUG("SSH_FXP_WRITE packet received (%" PRIuSIZE " bytes)...\r\n", totalLen);
393  TRACE_VERBOSE_ARRAY(" ", packet, fragLen);
394 
395  //Point to the first field of the packet
396  p = packet;
397 
398  //Malformed packet?
399  if(fragLen < sizeof(uint32_t) || fragLen > totalLen)
400  return ERROR_INVALID_PACKET;
401 
402  //Get request identifier
403  session->requestId = LOAD32BE(p);
404 
405  //Point to the next field
406  p += sizeof(uint32_t);
407  fragLen -= sizeof(uint32_t);
408  totalLen -= sizeof(uint32_t);
409 
410  //Get handle
411  error = sshParseBinaryString(p, fragLen, &handle);
412  //Any error to report?
413  if(error)
414  return error;
415 
416  //Point to the next field
417  p += sizeof(uint32_t) + handle.length;
418  fragLen -= sizeof(uint32_t) + handle.length;
419  totalLen -= sizeof(uint32_t) + handle.length;
420 
421  //Malformed packet?
422  if(fragLen < sizeof(uint64_t))
423  return ERROR_INVALID_PACKET;
424 
425  //The 'offset' field is the offset from the beginning of the file where
426  //to start writing
427  offset = LOAD64BE(p);
428 
429  //Point to the next field
430  p += sizeof(uint64_t);
431  fragLen -= sizeof(uint64_t);
432  totalLen -= sizeof(uint64_t);
433 
434  //Malformed packet?
435  if(fragLen < sizeof(uint32_t))
436  return ERROR_INVALID_PACKET;
437 
438  //The 'data' field is a byte string containing the data to be written
439  error = sshParseBinaryString(p, totalLen, &data);
440  //Any error to report?
441  if(error)
442  return error;
443 
444  //Malformed packet?
445  if(totalLen != (sizeof(uint32_t) + data.length))
446  return ERROR_INVALID_PACKET;
447 
448  //Point to the data payload
449  p += sizeof(uint32_t);
450  fragLen -= sizeof(uint32_t);
451  totalLen -= sizeof(uint32_t);
452 
453  //Write data to the specified file
454  error = sftpServerWriteFile(session, &handle, offset, p, fragLen, totalLen);
455 
456  //Return status code
457  return error;
458 }
459 
460 
461 /**
462  * @brief Parse SSH_FXP_OPENDIR packet
463  * @param[in] session Handle referencing an SFTP session
464  * @param[in] packet Pointer to packet
465  * @param[in] length Length of the packet, in bytes
466  * @return Error code
467  **/
468 
470  const uint8_t *packet, size_t length)
471 {
472  error_t error;
473  uint32_t id;
474  uint32_t handle;
475  const uint8_t *p;
476  SshString path;
477 
478  //Debug message
479  TRACE_INFO("SSH_FXP_OPENDIR packet received (%" PRIuSIZE " bytes)...\r\n", length);
480  TRACE_VERBOSE_ARRAY(" ", packet, length);
481 
482  //Point to the first field of the packet
483  p = packet;
484 
485  //Malformed packet?
486  if(length < sizeof(uint32_t))
487  return ERROR_INVALID_PACKET;
488 
489  //Get request identifier
490  id = LOAD32BE(p);
491 
492  //Point to the next field
493  p += sizeof(uint32_t);
494  length -= sizeof(uint32_t);
495 
496  //The path field specifies the path name of the directory to be listed
497  error = sshParseString(p, length, &path);
498  //Any error to report?
499  if(error)
500  return error;
501 
502  //Malformed message?
503  if(length != (sizeof(uint32_t) + path.length))
504  return ERROR_INVALID_PACKET;
505 
506  //Open the specified directory
507  error = sftpServerOpenDir(session, &path, &handle);
508 
509  //Check status code
510  if(error == NO_ERROR)
511  {
512  //The server will respond to this request with an SSH_FXP_HANDLE packet
513  error = sftpFormatFxpHandle(session, id, handle);
514  }
515  else if(error == ERROR_OUT_OF_RESOURCES)
516  {
517  //Too many files have been open
518  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
519  "Too many open files");
520  }
521  else if(error == ERROR_ACCESS_DENIED)
522  {
523  //The authenticated user does not have sufficient permissions to perform
524  //the operation
525  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
526  "Permission denied");
527  }
528  else
529  {
530  //The specified path name does not exist
531  error = sftpFormatFxpStatus(session, id, SSH_FX_NO_SUCH_FILE,
532  "No such directory");
533  }
534 
535  //Return status code
536  return error;
537 }
538 
539 
540 /**
541  * @brief Parse SSH_FXP_READDIR packet
542  * @param[in] session Handle referencing an SFTP session
543  * @param[in] packet Pointer to packet
544  * @param[in] length Length of the packet, in bytes
545  * @return Error code
546  **/
547 
549  const uint8_t *packet, size_t length)
550 {
551  error_t error;
552  uint32_t id;
553  const uint8_t *p;
554  SshBinaryString handle;
555  SftpName name;
556 
557  //Debug message
558  TRACE_DEBUG("SSH_FXP_READDIR packet received (%" PRIuSIZE " bytes)...\r\n", length);
559  TRACE_VERBOSE_ARRAY(" ", packet, length);
560 
561  //Point to the first field of the packet
562  p = packet;
563 
564  //Malformed packet?
565  if(length < sizeof(uint32_t))
566  return ERROR_INVALID_PACKET;
567 
568  //Get request identifier
569  id = LOAD32BE(p);
570 
571  //Point to the next field
572  p += sizeof(uint32_t);
573  length -= sizeof(uint32_t);
574 
575  //Get handle
576  error = sshParseBinaryString(p, length, &handle);
577  //Any error to report?
578  if(error)
579  return error;
580 
581  //Malformed message?
582  if(length != (sizeof(uint32_t) + handle.length))
583  return ERROR_INVALID_PACKET;
584 
585  //Read a new entry from the directory
586  error = sftpServerReadDir(session, &handle, &name);
587 
588  //Check status code
589  if(error == NO_ERROR)
590  {
591  //Each SSH_FXP_READDIR request returns one or more file names with full
592  //file attributes for each file
593  error = sftpFormatFxpName(session, id, &name);
594  }
595  else if(error == ERROR_END_OF_STREAM)
596  {
597  //Return an SSH_FX_EOF if there are no more files in the directory
598  error = sftpFormatFxpStatus(session, id, SSH_FX_EOF, "No more files");
599  }
600  else if(error == ERROR_INVALID_HANDLE)
601  {
602  //The supplied handle is not valid
603  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
604  "Invalid handle");
605  }
606  else
607  {
608  //Generic error
609  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
610  "Failed to read directory");
611  }
612 
613  //Return status code
614  return error;
615 }
616 
617 
618 /**
619  * @brief Parse SSH_FXP_REMOVE packet
620  * @param[in] session Handle referencing an SFTP session
621  * @param[in] packet Pointer to packet
622  * @param[in] length Length of the packet, in bytes
623  * @return Error code
624  **/
625 
627  const uint8_t *packet, size_t length)
628 {
629  error_t error;
630  uint32_t id;
631  const uint8_t *p;
633 
634  //Debug message
635  TRACE_INFO("SSH_FXP_REMOVE packet received (%" PRIuSIZE " bytes)...\r\n", length);
636  TRACE_VERBOSE_ARRAY(" ", packet, length);
637 
638  //Point to the first field of the packet
639  p = packet;
640 
641  //Malformed packet?
642  if(length < sizeof(uint32_t))
643  return ERROR_INVALID_PACKET;
644 
645  //Get request identifier
646  id = LOAD32BE(p);
647 
648  //Point to the next field
649  p += sizeof(uint32_t);
650  length -= sizeof(uint32_t);
651 
652  //The filename field specifies the file to be removed
653  error = sshParseString(p, length, &filename);
654  //Any error to report?
655  if(error)
656  return error;
657 
658  //Malformed message?
659  if(length != (sizeof(uint32_t) + filename.length))
660  return ERROR_INVALID_PACKET;
661 
662  //Remove the specified file
663  error = sftpServerRemoveFile(session, &filename);
664 
665  //Check status code
666  if(error == NO_ERROR)
667  {
668  //When the operation is successful, the server responds with an
669  //SSH_FXP_STATUS message with SSH_FX_OK status
670  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
671  }
672  else if(error == ERROR_ACCESS_DENIED)
673  {
674  //The authenticated user does not have sufficient permissions to perform
675  //the operation
676  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
677  "Permission denied");
678  }
679  else
680  {
681  //If an error occurs, the server responds with an SSH_FXP_STATUS
682  //message message indicating an failure
683  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
684  "Cannot remove file");
685  }
686 
687  //Return status code
688  return error;
689 }
690 
691 
692 /**
693  * @brief Parse SSH_FXP_MKDIR packet
694  * @param[in] session Handle referencing an SFTP session
695  * @param[in] packet Pointer to packet
696  * @param[in] length Length of the packet, in bytes
697  * @return Error code
698  **/
699 
701  const uint8_t *packet, size_t length)
702 {
703  error_t error;
704  size_t n;
705  uint32_t id;
706  const uint8_t *p;
707  SshString path;
709 
710  //Debug message
711  TRACE_INFO("SSH_FXP_MKDIR packet received (%" PRIuSIZE " bytes)...\r\n", length);
712  TRACE_VERBOSE_ARRAY(" ", packet, length);
713 
714  //Point to the first field of the packet
715  p = packet;
716 
717  //Malformed packet?
718  if(length < sizeof(uint32_t))
719  return ERROR_INVALID_PACKET;
720 
721  //Get request identifier
722  id = LOAD32BE(p);
723 
724  //Point to the next field
725  p += sizeof(uint32_t);
726  length -= sizeof(uint32_t);
727 
728  //The path field specifies the directory to be created
729  error = sshParseString(p, length, &path);
730  //Any error to report?
731  if(error)
732  return error;
733 
734  //Point to the next field
735  p += sizeof(uint32_t) + path.length;
736  length -= sizeof(uint32_t) + path.length;
737 
738  //Parse ATTRS compound data
739  error = sftpParseAttributes(session->version, &attributes, p, length, &n);
740  //Any error to report?
741  if(error)
742  return error;
743 
744  //Malformed packet?
745  if(length != n)
746  return ERROR_INVALID_PACKET;
747 
748  //Create the specified directory
749  error = sftpServerCreateDir(session, &path, &attributes);
750 
751  //Check status code
752  if(error == NO_ERROR)
753  {
754  //When the operation is successful, the server responds with an
755  //SSH_FXP_STATUS message with SSH_FX_OK status
756  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
757  }
758  else if(error == ERROR_ACCESS_DENIED)
759  {
760  //The authenticated user does not have sufficient permissions to perform
761  //the operation
762  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
763  "Permission denied");
764  }
765  else
766  {
767  //If an error occurs, the server responds with an SSH_FXP_STATUS
768  //message message indicating an failure
769  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
770  "Cannot create directory");
771  }
772 
773  //Return status code
774  return error;
775 }
776 
777 
778 /**
779  * @brief Parse SSH_FXP_RMDIR packet
780  * @param[in] session Handle referencing an SFTP session
781  * @param[in] packet Pointer to packet
782  * @param[in] length Length of the packet, in bytes
783  * @return Error code
784  **/
785 
787  const uint8_t *packet, size_t length)
788 {
789  error_t error;
790  uint32_t id;
791  const uint8_t *p;
792  SshString path;
793 
794  //Debug message
795  TRACE_INFO("SSH_FXP_RMDIR packet received (%" PRIuSIZE " bytes)...\r\n", length);
796  TRACE_VERBOSE_ARRAY(" ", packet, length);
797 
798  //Point to the first field of the packet
799  p = packet;
800 
801  //Malformed packet?
802  if(length < sizeof(uint32_t))
803  return ERROR_INVALID_PACKET;
804 
805  //Get request identifier
806  id = LOAD32BE(p);
807 
808  //Point to the next field
809  p += sizeof(uint32_t);
810  length -= sizeof(uint32_t);
811 
812  //The path field specifies the directory to be removed
813  error = sshParseString(p, length, &path);
814  //Any error to report?
815  if(error)
816  return error;
817 
818  //Malformed message?
819  if(length != (sizeof(uint32_t) + path.length))
820  return ERROR_INVALID_PACKET;
821 
822  //Remove the specified directory
823  error = sftpServerRemoveDir(session, &path);
824 
825  //Check status code
826  if(error == NO_ERROR)
827  {
828  //When the operation is successful, the server responds with an
829  //SSH_FXP_STATUS message with SSH_FX_OK status
830  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
831  }
832  else if(error == ERROR_ACCESS_DENIED)
833  {
834  //The authenticated user does not have sufficient permissions to perform
835  //the operation
836  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
837  "Permission denied");
838  }
839  else
840  {
841  //If an error occurs, the server responds with an SSH_FXP_STATUS
842  //message message indicating an failure
843  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
844  "Cannot remove directory");
845  }
846 
847  //Return status code
848  return error;
849 }
850 
851 
852 /**
853  * @brief Parse SSH_FXP_REALPATH packet
854  * @param[in] session Handle referencing an SFTP session
855  * @param[in] packet Pointer to packet
856  * @param[in] length Length of the packet, in bytes
857  * @return Error code
858  **/
859 
861  const uint8_t *packet, size_t length)
862 {
863  error_t error;
864  uint32_t id;
865  const uint8_t *p;
866  SshString path;
867  SftpName name;
868 
869  //Debug message
870  TRACE_INFO("SSH_FXP_REALPATH packet received (%" PRIuSIZE " bytes)...\r\n", length);
871  TRACE_VERBOSE_ARRAY(" ", packet, length);
872 
873  //Point to the first field of the packet
874  p = packet;
875 
876  //Malformed packet?
877  if(length < sizeof(uint32_t))
878  return ERROR_INVALID_PACKET;
879 
880  //Get request identifier
881  id = LOAD32BE(p);
882 
883  //Point to the next field
884  p += sizeof(uint32_t);
885  length -= sizeof(uint32_t);
886 
887  //The path field specifies the path name to be canonicalized
888  error = sshParseString(p, length, &path);
889  //Any error to report?
890  if(error)
891  return error;
892 
893  //Malformed message?
894  if(length != (sizeof(uint32_t) + path.length))
895  return ERROR_INVALID_PACKET;
896 
897  //Canonicalize the specified path name to an absolute path
898  error = sftpServerGetRealPath(session, &path, &name);
899 
900  //Check status code
901  if(!error)
902  {
903  //The server will respond with an SSH_FXP_NAME packet containing the
904  //name in canonical form and a dummy attributes value
905  error = sftpFormatFxpName(session, id, &name);
906  }
907  else
908  {
909  //If an error occurs, the server may also respond with SSH_FXP_STATUS
910  error = sftpFormatFxpStatus(session, id, SSH_FX_NO_SUCH_FILE,
911  "Invalid path");
912  }
913 
914  //Return status code
915  return error;
916 }
917 
918 
919 /**
920  * @brief Parse SSH_FXP_STAT packet
921  * @param[in] session Handle referencing an SFTP session
922  * @param[in] packet Pointer to packet
923  * @param[in] length Length of the packet, in bytes
924  * @return Error code
925  **/
926 
928  const uint8_t *packet, size_t length)
929 {
930  error_t error;
931  uint32_t id;
932  const uint8_t *p;
933  SshString path;
935 
936  //Debug message
937  TRACE_INFO("SSH_FXP_STAT packet received (%" PRIuSIZE " bytes)...\r\n", length);
938  TRACE_VERBOSE_ARRAY(" ", packet, length);
939 
940  //Point to the first field of the packet
941  p = packet;
942 
943  //Malformed packet?
944  if(length < sizeof(uint32_t))
945  return ERROR_INVALID_PACKET;
946 
947  //Get request identifier
948  id = LOAD32BE(p);
949 
950  //Point to the next field
951  p += sizeof(uint32_t);
952  length -= sizeof(uint32_t);
953 
954  //The path field specifies the file system object for which status is
955  //to be returned
956  error = sshParseString(p, length, &path);
957  //Any error to report?
958  if(error)
959  return error;
960 
961  //Malformed message?
962  if(length != (sizeof(uint32_t) + path.length))
963  return ERROR_INVALID_PACKET;
964 
965  //Retrieve the attributes of the specified file
966  error = sftpServerGetFileStat(session, &path, &attributes);
967 
968  //Check status code
969  if(error == NO_ERROR)
970  {
971  //The server responds to this request with SSH_FXP_ATTRS
972  error = sftpFormatFxpAttrs(session, id, &attributes);
973  }
974  else if(error == ERROR_ACCESS_DENIED)
975  {
976  //The authenticated user does not have sufficient permissions to perform
977  //the operation
978  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
979  "Permission denied");
980  }
981  else
982  {
983  //If an error occurs, the server may also respond with SSH_FXP_STATUS
984  error = sftpFormatFxpStatus(session, id, SSH_FX_NO_SUCH_FILE,
985  "No such file");
986  }
987 
988  //Return status code
989  return error;
990 }
991 
992 
993 /**
994  * @brief Parse SSH_FXP_FSTAT packet
995  * @param[in] session Handle referencing an SFTP session
996  * @param[in] packet Pointer to packet
997  * @param[in] length Length of the packet, in bytes
998  * @return Error code
999  **/
1000 
1002  const uint8_t *packet, size_t length)
1003 {
1004  error_t error;
1005  uint32_t id;
1006  const uint8_t *p;
1007  SshBinaryString handle;
1009 
1010  //Debug message
1011  TRACE_INFO("SSH_FXP_FSTAT packet received (%" PRIuSIZE " bytes)...\r\n", length);
1012  TRACE_VERBOSE_ARRAY(" ", packet, length);
1013 
1014  //Point to the first field of the packet
1015  p = packet;
1016 
1017  //Malformed packet?
1018  if(length < sizeof(uint32_t))
1019  return ERROR_INVALID_PACKET;
1020 
1021  //Get request identifier
1022  id = LOAD32BE(p);
1023 
1024  //Point to the next field
1025  p += sizeof(uint32_t);
1026  length -= sizeof(uint32_t);
1027 
1028  //Get handle
1029  error = sshParseBinaryString(p, length, &handle);
1030  //Any error to report?
1031  if(error)
1032  return error;
1033 
1034  //Malformed message?
1035  if(length != (sizeof(uint32_t) + handle.length))
1036  return ERROR_INVALID_PACKET;
1037 
1038  //Retrieve the attributes of the specified file
1039  error = sftpServerGetFileStatEx(session, &handle, &attributes);
1040 
1041  //Check status code
1042  if(error == NO_ERROR)
1043  {
1044  //The server responds to this request with SSH_FXP_ATTRS
1045  error = sftpFormatFxpAttrs(session, id, &attributes);
1046  }
1047  else if(error == ERROR_ACCESS_DENIED)
1048  {
1049  //The authenticated user does not have sufficient permissions to perform
1050  //the operation
1051  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
1052  "Permission denied");
1053  }
1054  else
1055  {
1056  //If an error occurs, the server may also respond with SSH_FXP_STATUS
1057  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
1058  "Invalid handle");
1059  }
1060 
1061  //Return status code
1062  return error;
1063 }
1064 
1065 
1066 /**
1067  * @brief Parse SSH_FXP_SETSTAT packet
1068  * @param[in] session Handle referencing an SFTP session
1069  * @param[in] packet Pointer to packet
1070  * @param[in] length Length of the packet, in bytes
1071  * @return Error code
1072  **/
1073 
1075  const uint8_t *packet, size_t length)
1076 {
1077  error_t error;
1078  size_t n;
1079  uint32_t id;
1080  const uint8_t *p;
1081  SshString path;
1083 
1084  //Debug message
1085  TRACE_INFO("SSH_FXP_SETSTAT packet received (%" PRIuSIZE " bytes)...\r\n", length);
1086  TRACE_VERBOSE_ARRAY(" ", packet, length);
1087 
1088  //Point to the first field of the packet
1089  p = packet;
1090 
1091  //Malformed packet?
1092  if(length < sizeof(uint32_t))
1093  return ERROR_INVALID_PACKET;
1094 
1095  //Get request identifier
1096  id = LOAD32BE(p);
1097 
1098  //Point to the next field
1099  p += sizeof(uint32_t);
1100  length -= sizeof(uint32_t);
1101 
1102  //The path field specifies the file system object for which status is
1103  //to be returned
1104  error = sshParseString(p, length, &path);
1105  //Any error to report?
1106  if(error)
1107  return error;
1108 
1109  //Point to the next field
1110  p += sizeof(uint32_t) + path.length;
1111  length -= sizeof(uint32_t) + path.length;
1112 
1113  //Parse ATTRS compound data
1114  error = sftpParseAttributes(session->version, &attributes, p, length, &n);
1115  //Any error to report?
1116  if(error)
1117  return error;
1118 
1119  //Malformed packet?
1120  if(length != n)
1121  return ERROR_INVALID_PACKET;
1122 
1123  //Modify the attributes of the specified file
1124  error = sftpServerSetFileStat(session, &path, &attributes);
1125 
1126  //Check status code
1127  if(error == NO_ERROR)
1128  {
1129  //When the operation is successful, the server responds with an
1130  //SSH_FXP_STATUS message with SSH_FX_OK status
1131  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
1132  }
1133  else if(error == ERROR_ACCESS_DENIED)
1134  {
1135  //The authenticated user does not have sufficient permissions to perform
1136  //the operation
1137  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
1138  "Permission denied");
1139  }
1140  else
1141  {
1142  //If an error occurs, the server responds with an SSH_FXP_STATUS
1143  //message message indicating an failure
1144  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
1145  "Invalid handle");
1146  }
1147 
1148  //Return status code
1149  return error;
1150 }
1151 
1152 
1153 /**
1154  * @brief Parse SSH_FXP_FSETSTAT packet
1155  * @param[in] session Handle referencing an SFTP session
1156  * @param[in] packet Pointer to packet
1157  * @param[in] length Length of the packet, in bytes
1158  * @return Error code
1159  **/
1160 
1162  const uint8_t *packet, size_t length)
1163 {
1164  error_t error;
1165  size_t n;
1166  uint32_t id;
1167  const uint8_t *p;
1168  SshBinaryString handle;
1170 
1171  //Debug message
1172  TRACE_INFO("SSH_FXP_FSETSTAT packet received (%" PRIuSIZE " bytes)...\r\n", length);
1173  TRACE_VERBOSE_ARRAY(" ", packet, length);
1174 
1175  //Point to the first field of the packet
1176  p = packet;
1177 
1178  //Malformed packet?
1179  if(length < sizeof(uint32_t))
1180  return ERROR_INVALID_PACKET;
1181 
1182  //Get request identifier
1183  id = LOAD32BE(p);
1184 
1185  //Point to the next field
1186  p += sizeof(uint32_t);
1187  length -= sizeof(uint32_t);
1188 
1189  //Get handle
1190  error = sshParseBinaryString(p, length, &handle);
1191  //Any error to report?
1192  if(error)
1193  return error;
1194 
1195  //Point to the next field
1196  p += sizeof(uint32_t) + handle.length;
1197  length -= sizeof(uint32_t) + handle.length;
1198 
1199  //Parse ATTRS compound data
1200  error = sftpParseAttributes(session->version, &attributes, p, length, &n);
1201  //Any error to report?
1202  if(error)
1203  return error;
1204 
1205  //Malformed packet?
1206  if(length != n)
1207  return ERROR_INVALID_PACKET;
1208 
1209  //Modify the attributes of the specified file
1210  error = sftpServerSetFileStatEx(session, &handle, &attributes);
1211 
1212  //Check status code
1213  if(error == NO_ERROR)
1214  {
1215  //When the operation is successful, the server responds with an
1216  //SSH_FXP_STATUS message with SSH_FX_OK status
1217  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
1218  }
1219  else if(error == ERROR_ACCESS_DENIED)
1220  {
1221  //The authenticated user does not have sufficient permissions to perform
1222  //the operation
1223  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
1224  "Permission denied");
1225  }
1226  else
1227  {
1228  //If an error occurs, the server responds with an SSH_FXP_STATUS
1229  //message message indicating an failure
1230  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
1231  "Invalid handle");
1232  }
1233 
1234  //Return status code
1235  return error;
1236 }
1237 
1238 
1239 /**
1240  * @brief Parse SSH_FXP_RENAME packet
1241  * @param[in] session Handle referencing an SFTP session
1242  * @param[in] packet Pointer to packet
1243  * @param[in] length Length of the packet, in bytes
1244  * @return Error code
1245  **/
1246 
1248  const uint8_t *packet, size_t length)
1249 {
1250  error_t error;
1251  uint32_t id;
1252  const uint8_t *p;
1253  SshString oldPath;
1254  SshString newPath;
1255 
1256  //Debug message
1257  TRACE_INFO("SSH_FXP_RENAME packet received (%" PRIuSIZE " bytes)...\r\n", length);
1258  TRACE_VERBOSE_ARRAY(" ", packet, length);
1259 
1260  //Point to the first field of the packet
1261  p = packet;
1262 
1263  //Malformed packet?
1264  if(length < sizeof(uint32_t))
1265  return ERROR_INVALID_PACKET;
1266 
1267  //Get request identifier
1268  id = LOAD32BE(p);
1269 
1270  //Point to the next field
1271  p += sizeof(uint32_t);
1272  length -= sizeof(uint32_t);
1273 
1274  //The oldpath field is the name of an existing file or directory
1275  error = sshParseString(p, length, &oldPath);
1276  //Any error to report?
1277  if(error)
1278  return error;
1279 
1280  //Point to the next field
1281  p += sizeof(uint32_t) + oldPath.length;
1282  length -= sizeof(uint32_t) + oldPath.length;
1283 
1284  //The newpath field is the new name for the file or directory
1285  error = sshParseString(p, length, &newPath);
1286  //Any error to report?
1287  if(error)
1288  return error;
1289 
1290  //Malformed message?
1291  if(length != (sizeof(uint32_t) + newPath.length))
1292  return ERROR_INVALID_PACKET;
1293 
1294  //Rename the specified file
1295  error = sftpServerRenameFile(session, &oldPath, &newPath);
1296 
1297  //Check status code
1298  if(error == NO_ERROR)
1299  {
1300  //When the operation is successful, the server responds with an
1301  //SSH_FXP_STATUS message with SSH_FX_OK status
1302  error = sftpFormatFxpStatus(session, id, SSH_FX_OK, "Success");
1303  }
1304  else if(error == ERROR_ACCESS_DENIED)
1305  {
1306  //The authenticated user does not have sufficient permissions to perform
1307  //the operation
1308  error = sftpFormatFxpStatus(session, id, SSH_FX_PERMISSION_DENIED,
1309  "Permission denied");
1310  }
1311  else
1312  {
1313  //If an error occurs, the server responds with an SSH_FXP_STATUS
1314  //message message indicating an failure
1315  error = sftpFormatFxpStatus(session, id, SSH_FX_FAILURE,
1316  "Cannot rename file");
1317  }
1318 
1319  //Return status code
1320  return error;
1321 }
1322 
1323 
1324 /**
1325  * @brief Parse SSH_FXP_EXTENDED packet
1326  * @param[in] session Handle referencing an SFTP session
1327  * @param[in] packet Pointer to packet
1328  * @param[in] length Length of the packet, in bytes
1329  * @return Error code
1330  **/
1331 
1333  const uint8_t *packet, size_t length)
1334 {
1335  error_t error;
1336  uint32_t id;
1337  const uint8_t *p;
1338  SshString extendedRequest;
1339 
1340  //Debug message
1341  TRACE_INFO("SSH_FXP_EXTENDED packet received (%" PRIuSIZE " bytes)...\r\n", length);
1342  TRACE_VERBOSE_ARRAY(" ", packet, length);
1343 
1344  //Point to the first field of the packet
1345  p = packet;
1346 
1347  //Malformed packet?
1348  if(length < sizeof(uint32_t))
1349  return ERROR_INVALID_PACKET;
1350 
1351  //Get request identifier
1352  id = LOAD32BE(p);
1353 
1354  //Point to the next field
1355  p += sizeof(uint32_t);
1356  length -= sizeof(uint32_t);
1357 
1358  //The 'extended-request' field is a string of the format "name@domain", where
1359  //domain is an Internet domain name of the vendor defining the request
1360  error = sshParseString(p, length, &extendedRequest);
1361  //Any error to report?
1362  if(error)
1363  return error;
1364 
1365  //If the server does not recognize the 'extended-request' name, then
1366  //the server must respond with SSH_FXP_STATUS with error/status set to
1367  //SSH_FX_OP_UNSUPPORTED
1368  error = sftpFormatFxpStatus(session, id, SSH_FX_OP_UNSUPPORTED,
1369  "Extended request not supported");
1370 
1371  //Return status code
1372  return error;
1373 }
1374 
1375 
1376 /**
1377  * @brief Format SSH_FXP_VERSION packet
1378  * @param[in] session Handle referencing an SFTP session
1379  * @param[in] version Protocol version number
1380  * @return Error code
1381  **/
1382 
1384 {
1385  size_t length;
1386  uint8_t *p;
1387  SftpPacketHeader *header;
1388 
1389  //Point to the buffer where to format the packet
1390  header = (SftpPacketHeader *) session->buffer;
1391 
1392  //Set packet type
1393  header->type = SSH_FXP_VERSION;
1394  //Total length of the packet
1395  length = sizeof(uint8_t);
1396 
1397  //Point the data payload
1398  p = header->payload;
1399 
1400  //The SSH_FXP_VERSION packet contains the lowest of its own and the
1401  //client's version number
1402  STORE32BE(version, p);
1403 
1404  //Total length of the packet
1405  length += sizeof(uint32_t);
1406 
1407  //Convert the length field to network byte order
1408  header->length = htonl(length);
1409 
1410  //The packet length does not include the length field itself
1411  session->bufferLen = length + sizeof(uint32_t);
1412  session->bufferPos = 0;
1413 
1414  //Debug message
1415  TRACE_INFO("Sending SSH_FXP_VERSION packet (%" PRIuSIZE " bytes)...\r\n", session->bufferLen);
1416  TRACE_VERBOSE_ARRAY(" ", session->buffer, session->bufferLen);
1417 
1418  //Send the packet to the SFTP client
1419  session->state = SFTP_SERVER_SESSION_STATE_SENDING;
1420 
1421  //Successful processing
1422  return NO_ERROR;
1423 }
1424 
1425 
1426 /**
1427  * @brief Format SSH_FXP_STATUS message
1428  * @param[in] session Handle referencing an SFTP session
1429  * @param[in] id Request identifier
1430  * @param[in] statusCode Result of the requested operation
1431  * @param[in] message NULL-terminating description string
1432  * @return Error code
1433  **/
1434 
1436  uint32_t statusCode, const char_t *message)
1437 {
1438  error_t error;
1439  size_t n;
1440  size_t length;
1441  uint8_t *p;
1442  SftpPacketHeader *header;
1443 
1444  //Point to the buffer where to format the packet
1445  header = (SftpPacketHeader *) session->buffer;
1446 
1447  //Set packet type
1448  header->type = SSH_FXP_STATUS;
1449  //Total length of the packet
1450  length = sizeof(uint8_t);
1451 
1452  //Point the data payload
1453  p = header->payload;
1454 
1455  //Format request identifier
1456  STORE32BE(id, p);
1457 
1458  //Point to the next field
1459  p += sizeof(uint32_t);
1460  length += sizeof(uint32_t);
1461 
1462  //Format status code
1463  STORE32BE(statusCode, p);
1464 
1465  //Point to the next field
1466  p += sizeof(uint32_t);
1467  length += sizeof(uint32_t);
1468 
1469  //Copy the description string
1470  error = sshFormatString(message, p, &n);
1471  //Any error to report?
1472  if(error)
1473  return error;
1474 
1475  //Point to the next field
1476  p += n;
1477  length += n;
1478 
1479  //Set language tag
1480  error = sshFormatString("en", p, &n);
1481  //Any error to report?
1482  if(error)
1483  return error;
1484 
1485  //Total length of the message
1486  length += n;
1487 
1488  //Convert the length field to network byte order
1489  header->length = htonl(length);
1490 
1491  //The packet length does not include the length field itself
1492  session->bufferLen = length + sizeof(uint32_t);
1493  session->bufferPos = 0;
1494 
1495  //Debug message
1496  TRACE_DEBUG("Sending SSH_FXP_STATUS packet (%" PRIuSIZE " bytes)...\r\n", session->bufferLen);
1497  TRACE_VERBOSE_ARRAY(" ", session->buffer, session->bufferLen);
1498 
1499  //Send the packet to the SFTP client
1500  session->state = SFTP_SERVER_SESSION_STATE_SENDING;
1501 
1502  //Successful processing
1503  return NO_ERROR;
1504 }
1505 
1506 
1507 /**
1508  * @brief Format SSH_FXP_HANDLE message
1509  * @param[in] session Handle referencing an SFTP session
1510  * @param[in] id Request identifier
1511  * @param[in] handle Opaque value that identifies a file or directory
1512  * @return Error code
1513  **/
1514 
1516  uint32_t handle)
1517 {
1518  size_t length;
1519  uint8_t *p;
1520  SftpPacketHeader *header;
1521 
1522  //Point to the buffer where to format the packet
1523  header = (SftpPacketHeader *) session->buffer;
1524 
1525  //Set packet type
1526  header->type = SSH_FXP_HANDLE;
1527  //Total length of the packet
1528  length = sizeof(uint8_t);
1529 
1530  //Point the data payload
1531  p = header->payload;
1532 
1533  //Format request identifier
1534  STORE32BE(id, p);
1535 
1536  //Point to the next field
1537  p += sizeof(uint32_t);
1538  length += sizeof(uint32_t);
1539 
1540  //The handle field is an arbitrary string that identifies a file or
1541  //directory on the server
1542  STORE32BE(handle, p + sizeof(uint32_t));
1543 
1544  //The string is preceded by a uint32 containing its length
1545  STORE32BE(sizeof(uint32_t), p);
1546 
1547  //Total length of the message
1548  length += 2 * sizeof(uint32_t);
1549 
1550  //Convert the length field to network byte order
1551  header->length = htonl(length);
1552 
1553  //The packet length does not include the length field itself
1554  session->bufferLen = length + sizeof(uint32_t);
1555  session->bufferPos = 0;
1556 
1557  //Debug message
1558  TRACE_INFO("Sending SSH_FXP_HANDLE packet (%" PRIuSIZE " bytes)...\r\n", session->bufferLen);
1559  TRACE_VERBOSE_ARRAY(" ", session->buffer, session->bufferLen);
1560 
1561  //Send the packet to the SFTP client
1562  session->state = SFTP_SERVER_SESSION_STATE_SENDING;
1563 
1564  //Successful processing
1565  return NO_ERROR;
1566 }
1567 
1568 
1569 /**
1570  * @brief Format SSH_FXP_DATA message
1571  * @param[in] session Handle referencing an SFTP session
1572  * @param[in] id Request identifier
1573  * @param[in] dataLen Length of the data string, in bytes
1574  * @return Error code
1575  **/
1576 
1578  size_t dataLen)
1579 {
1580  size_t length;
1581  uint8_t *p;
1582  SftpPacketHeader *header;
1583 
1584  //Point to the buffer where to format the packet
1585  header = (SftpPacketHeader *) session->buffer;
1586 
1587  //Set packet type
1588  header->type = SSH_FXP_DATA;
1589  //Total length of the packet
1590  length = sizeof(uint8_t);
1591 
1592  //Point the data payload
1593  p = header->payload;
1594 
1595  //Format request identifier
1596  STORE32BE(id, p);
1597 
1598  //Point to the next field
1599  p += sizeof(uint32_t);
1600  length += sizeof(uint32_t);
1601 
1602  //The data string is preceded by a uint32 containing its length
1603  STORE32BE(dataLen, p);
1604 
1605  //Point to the data payload
1606  p += sizeof(uint32_t);
1607  length += sizeof(uint32_t);
1608 
1609  //Convert the length field to network byte order
1610  header->length = htonl(length + dataLen);
1611 
1612  //The packet length does not include the length field itself
1613  session->bufferLen = length + sizeof(uint32_t);
1614  session->bufferPos = 0;
1615 
1616  //Debug message
1617  TRACE_DEBUG("Sending SSH_FXP_DATA packet (%" PRIuSIZE " bytes)...\r\n",
1618  session->bufferLen + session->dataLen);
1619  TRACE_VERBOSE_ARRAY(" ", session->buffer, session->bufferLen);
1620 
1621  //Send the packet to the SFTP client
1622  session->state = SFTP_SERVER_SESSION_STATE_SENDING_DATA;
1623 
1624  //Successful processing
1625  return NO_ERROR;
1626 }
1627 
1628 
1629 /**
1630  * @brief Format SSH_FXP_NAME packet
1631  * @param[in] session Handle referencing an SFTP session
1632  * @param[in] id Request identifier
1633  * @param[in] name Pointer to the name structure
1634  * @return Error code
1635  **/
1636 
1638  const SftpName *name)
1639 {
1640  error_t error;
1641  size_t n;
1642  size_t length;
1643  uint8_t *p;
1644  SftpPacketHeader *header;
1645 
1646  //Point to the buffer where to format the packet
1647  header = (SftpPacketHeader *) session->buffer;
1648 
1649  //Set packet type
1650  header->type = SSH_FXP_NAME;
1651  //Total length of the packet
1652  length = sizeof(uint8_t);
1653 
1654  //Point the data payload
1655  p = header->payload;
1656 
1657  //Format request identifier
1658  STORE32BE(id, p);
1659 
1660  //Point to the next field
1661  p += sizeof(uint32_t);
1662  length += sizeof(uint32_t);
1663 
1664  //Number of names returned in this response
1665  STORE32BE(1, p);
1666 
1667  //Point to the next field
1668  p += sizeof(uint32_t);
1669  length += sizeof(uint32_t);
1670 
1671  //Format name structure
1672  error = sftpFormatName(session->version, name, p, &n);
1673  //Any error to report?
1674  if(error)
1675  return error;
1676 
1677  //Total length of the message
1678  length += n;
1679 
1680  //Convert the length field to network byte order
1681  header->length = htonl(length);
1682 
1683  //The packet length does not include the length field itself
1684  session->bufferLen = length + sizeof(uint32_t);
1685  session->bufferPos = 0;
1686 
1687  //Debug message
1688  TRACE_DEBUG("Sending SSH_FXP_NAME packet (%" PRIuSIZE " bytes)...\r\n", session->bufferLen);
1689  TRACE_VERBOSE_ARRAY(" ", session->buffer, session->bufferLen);
1690 
1691  //Send the packet to the SFTP client
1692  session->state = SFTP_SERVER_SESSION_STATE_SENDING;
1693 
1694  //Successful processing
1695  return NO_ERROR;
1696 }
1697 
1698 
1699 /**
1700  * @brief Format SSH_FXP_ATTRS packet
1701  * @param[in] session Handle referencing an SFTP session
1702  * @param[in] id Request identifier
1703  * @param[in] attributes File attributes
1704  * @return Error code
1705  **/
1706 
1708  const SftpFileAttrs *attributes)
1709 {
1710  error_t error;
1711  size_t n;
1712  size_t length;
1713  uint8_t *p;
1714  SftpPacketHeader *header;
1715 
1716  //Point to the buffer where to format the packet
1717  header = (SftpPacketHeader *) session->buffer;
1718 
1719  //Set packet type
1720  header->type = SSH_FXP_ATTRS;
1721  //Total length of the packet
1722  length = sizeof(uint8_t);
1723 
1724  //Point the data payload
1725  p = header->payload;
1726 
1727  //Format request identifier
1728  STORE32BE(id, p);
1729 
1730  //Point to the next field
1731  p += sizeof(uint32_t);
1732  length += sizeof(uint32_t);
1733 
1734  //Format ATTRS compound data
1735  error = sftpFormatAttributes(session->version, attributes, p, &n);
1736  //Any error to report?
1737  if(error)
1738  return error;
1739 
1740  //Total length of the message
1741  length += n;
1742 
1743  //Convert the length field to network byte order
1744  header->length = htonl(length);
1745 
1746  //The packet length does not include the length field itself
1747  session->bufferLen = length + sizeof(uint32_t);
1748  session->bufferPos = 0;
1749 
1750  //Debug message
1751  TRACE_INFO("Sending SSH_FXP_ATTRS packet (%" PRIuSIZE " bytes)...\r\n", session->bufferLen);
1752  TRACE_VERBOSE_ARRAY(" ", session->buffer, session->bufferLen);
1753 
1754  //Send the packet to the SFTP client
1755  session->state = SFTP_SERVER_SESSION_STATE_SENDING;
1756 
1757  //Successful processing
1758  return NO_ERROR;
1759 }
1760 
1761 #endif
error_t sftpServerOpenDir(SftpServerSession *session, const SshString *path, uint32_t *handle)
Open a directory.
error_t sftpServerParseFxpMkDir(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_MKDIR packet.
error_t sftpServerWriteFile(SftpServerSession *session, const SshBinaryString *handle, uint64_t offset, const uint8_t *data, uint32_t fragLen, uint32_t totalLen)
Write the specified file.
Path manipulation helper functions.
@ SSH_FXP_ATTRS
Definition: sftp_common.h:159
error_t sftpServerCloseDir(SftpServerSession *session, const SshBinaryString *handle)
Close a directory.
@ SSH_FX_PERMISSION_DENIED
Definition: sftp_common.h:174
error_t sftpServerParseFxpSetStat(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_SETSTAT packet.
error_t sftpServerParseFxpFstat(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_FSTAT packet.
#define LOAD32BE(p)
Definition: cpu_endian.h:210
Binary string.
Definition: ssh_types.h:67
error_t sftpServerParseFxpRename(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_RENAME packet.
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
error_t sftpServerReadDir(SftpServerSession *session, const SshBinaryString *handle, SftpName *name)
Read an entry from the specified directory.
uint8_t data[]
Definition: ethernet.h:224
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
error_t sftpFormatName(SftpVersion version, const SftpName *name, uint8_t *p, size_t *written)
Format name structure.
Definition: sftp_common.c:50
error_t sftpServerRemoveDir(SftpServerSession *session, const SshString *path)
Remove a directory.
error_t sshParseString(const uint8_t *p, size_t length, SshString *string)
Parse a string.
Definition: ssh_misc.c:1178
uint8_t attributes[]
Definition: radius.h:90
@ SSH_FXP_STATUS
Definition: sftp_common.h:155
char_t name[]
size_t length
Definition: ssh_types.h:58
error_t sftpServerReadFile(SftpServerSession *session, const SshBinaryString *handle, uint64_t offset, uint32_t *length)
Read the specified file.
#define SFTP_SERVER_MAX_VERSION
Definition: sftp_server.h:81
uint8_t version
Definition: coap_common.h:177
@ ERROR_INVALID_HANDLE
Definition: error.h:282
@ ERROR_END_OF_STREAM
Definition: error.h:211
error_t sftpServerParseFxpSetFstat(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_FSETSTAT packet.
@ ERROR_INVALID_VERSION
Definition: error.h:118
@ SSH_FXP_HANDLE
Definition: sftp_common.h:156
SFTP server.
error_t sftpServerParseFxpRead(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_READ packet.
#define LOAD64BE(p)
Definition: cpu_endian.h:246
@ SSH_FXP_VERSION
Definition: sftp_common.h:136
error_t sftpServerParseFxpInit(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_INIT packet.
error_t sftpFormatFxpName(SftpServerSession *session, uint32_t id, const SftpName *name)
Format SSH_FXP_NAME packet.
size_t length
Definition: ssh_types.h:69
Directory operations.
#define htonl(value)
Definition: cpu_endian.h:414
#define SFTP_SERVER_MIN_VERSION
Definition: sftp_server.h:74
error_t sftpServerParseFxpOpen(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_OPEN packet.
error_t
Error codes.
Definition: error.h:43
error_t sftpServerParseFxpExtended(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_EXTENDED packet.
File operations.
error_t sftpParseAttributes(SftpVersion version, SftpFileAttrs *attributes, const uint8_t *data, size_t length, size_t *consumed)
Parse file attributes.
Definition: sftp_common.c:454
error_t sftpServerGetRealPath(SftpServerSession *session, const SshString *path, SftpName *name)
Canonicalize a given path name to an absolute path.
error_t sftpFormatAttributes(SftpVersion version, const SftpFileAttrs *attributes, uint8_t *p, size_t *written)
Format file attributes.
Definition: sftp_common.c:255
SftpPacketHeader
Definition: sftp_common.h:219
error_t sftpServerRemoveFile(SftpServerSession *session, const SshString *path)
Remove a file.
error_t sftpServerParseFxpOpenDir(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_OPENDIR packet.
error_t sftpServerParseFxpWrite(SftpServerSession *session, const uint8_t *packet, size_t fragLen, size_t totalLen)
Parse SSH_FXP_WRITE packet.
@ SSH_FXP_DATA
Definition: sftp_common.h:157
error_t sftpFormatFxpStatus(SftpServerSession *session, uint32_t id, uint32_t statusCode, const char_t *message)
Format SSH_FXP_STATUS message.
error_t sftpFormatFxpData(SftpServerSession *session, uint32_t id, size_t dataLen)
Format SSH_FXP_DATA message.
@ ERROR_INVALID_PACKET
Definition: error.h:141
error_t sftpServerRenameFile(SftpServerSession *session, const SshString *oldPath, const SshString *newPath)
Rename the specified file.
@ SSH_FX_FAILURE
Definition: sftp_common.h:175
char_t filename[]
Definition: tftp_common.h:93
error_t sftpServerCloseFile(SftpServerSession *session, const SshBinaryString *handle)
Close a file.
@ ERROR_ACCESS_DENIED
Definition: error.h:149
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
@ SSH_FX_OK
Definition: sftp_common.h:171
@ SSH_FX_OP_UNSUPPORTED
Definition: sftp_common.h:179
#define MIN(a, b)
Definition: os_port.h:63
error_t sftpFormatFxpAttrs(SftpServerSession *session, uint32_t id, const SftpFileAttrs *attributes)
Format SSH_FXP_ATTRS packet.
@ SSH_FXP_NAME
Definition: sftp_common.h:158
SFTP packet parsing and formatting.
@ SFTP_SERVER_SESSION_STATE_SENDING_DATA
Definition: sftp_server.h:171
String.
Definition: ssh_types.h:56
uint32_t dataLen
Definition: sftp_common.h:229
error_t sftpServerParseFxpClose(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_CLOSE packet.
error_t sftpServerOpenFile(SftpServerSession *session, const SshString *path, uint32_t pflags, const SftpFileAttrs *attributes, uint32_t *handle)
Open a file.
#define TRACE_DEBUG(...)
Definition: debug.h:119
char char_t
Definition: compiler_port.h:55
Name structure.
Definition: sftp_common.h:265
error_t sftpServerSetFileStat(SftpServerSession *session, const SshString *path, const SftpFileAttrs *attributes)
Modify file attributes.
error_t sftpFormatFxpHandle(SftpServerSession *session, uint32_t id, uint32_t handle)
Format SSH_FXP_HANDLE message.
uint8_t n
error_t sftpServerParseFxpRealPath(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_REALPATH packet.
error_t sftpServerParseFxpStat(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_STAT packet.
error_t sftpServerParseFxpReadDir(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_READDIR packet.
Helper functions for SFTP server.
SSH helper functions.
error_t sftpFormatFxpVersion(SftpServerSession *session, uint32_t version)
Format SSH_FXP_VERSION packet.
error_t sftpServerSetFileStatEx(SftpServerSession *session, const SshBinaryString *handle, const SftpFileAttrs *attributes)
Modify file attributes.
SftpVersion
SFTP protocol version.
Definition: sftp_common.h:118
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1215
error_t sshFormatString(const char_t *value, uint8_t *p, size_t *written)
Format a string.
Definition: ssh_misc.c:1410
#define SftpServerSession
Definition: sftp_server.h:130
#define PRIuSIZE
File attributes.
Definition: sftp_common.h:247
error_t sftpServerGetFileStat(SftpServerSession *session, const SshString *path, SftpFileAttrs *attributes)
Retrieve file attributes.
error_t sftpServerCreateDir(SftpServerSession *session, const SshString *path, const SftpFileAttrs *attributes)
Create a directory.
error_t sftpServerParseFxpRemove(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_REMOVE packet.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ SSH_FX_EOF
Definition: sftp_common.h:172
error_t sftpServerGetFileStatEx(SftpServerSession *session, const SshBinaryString *handle, SftpFileAttrs *attributes)
Retrieve file attributes.
@ SFTP_SERVER_SESSION_STATE_SENDING
Definition: sftp_server.h:169
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t sftpServerParseFxpRmDir(SftpServerSession *session, const uint8_t *packet, size_t length)
Parse SSH_FXP_RMDIR packet.
@ SSH_FX_NO_SUCH_FILE
Definition: sftp_common.h:173
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:140