sftp_client_packet.c
Go to the documentation of this file.
1 /**
2  * @file sftp_client_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.h"
36 #include "ssh/ssh_misc.h"
38 #include "sftp/sftp_client_misc.h"
39 #include "path.h"
40 #include "debug.h"
41 
42 //Check SSH stack configuration
43 #if (SFTP_CLIENT_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Format SSH_FXP_INIT packet
48  * @param[in] context Pointer to the SFTP client context
49  * @param[in] version Protocol version number
50  * @return Error code
51  **/
52 
54  uint32_t version)
55 {
56  size_t length;
57  uint8_t *p;
58  SftpPacketHeader *header;
59 
60  //Point to the buffer where to format the packet
61  header = (SftpPacketHeader *) context->buffer;
62 
63  //Set packet type
64  header->type = SSH_FXP_INIT;
65  //Total length of the packet
66  length = sizeof(uint8_t);
67 
68  //Point the data payload
69  p = header->payload;
70 
71  //The SSH_FXP_INIT packet contains the client version
73 
74  //Total length of the packet
75  length += sizeof(uint32_t);
76 
77  //Convert the length field to network byte order
78  header->length = htonl(length);
79 
80  //The packet length does not include the length field itself
81  context->requestLen = length + sizeof(uint32_t);
82  context->requestPos = 0;
83  context->responseLen = 0;
84  context->responsePos = 0;
85 
86  //Save the SFTP packet type
87  context->requestType = (SftpPacketType) header->type;
88 
89  //Debug message
90  TRACE_INFO("Sending SSH_FXP_INIT packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
91  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
92 
93  //Successful processing
94  return NO_ERROR;
95 }
96 
97 
98 /**
99  * @brief Format SSH_FXP_OPEN packet
100  * @param[in] context Pointer to the SFTP client context
101  * @param[in] filename Name to the file to be be opened or created
102  * @param[in] pflags File access mode
103  * @return Error code
104  **/
105 
107  const char_t *filename, uint32_t pflags)
108 {
109  error_t error;
110  size_t n;
111  size_t length;
112  uint8_t *p;
113  SftpPacketHeader *header;
115 
116  //Point to the buffer where to format the packet
117  header = (SftpPacketHeader *) context->buffer;
118 
119  //Set packet type
120  header->type = SSH_FXP_OPEN;
121  //Total length of the packet
122  length = sizeof(uint8_t);
123 
124  //Point the data payload
125  p = header->payload;
126 
127  //The request identifier is used to match each response with the
128  //corresponding request
129  context->requestId++;
130 
131  //Format request identifier
132  STORE32BE(context->requestId, p);
133 
134  //Point to the next field
135  p += sizeof(uint32_t);
136  length += sizeof(uint32_t);
137 
138  //The filename field specifies the name to the file to be be opened
139  error = sftpFormatPath(context, filename, p, &n);
140  //Any error to report?
141  if(error)
142  return error;
143 
144  //Point to the next field
145  p += n;
146  length += n;
147 
148  //Encode pflags field
149  STORE32BE(pflags, p);
150 
151  //Point to the next field
152  p += sizeof(uint32_t);
153  length += sizeof(uint32_t);
154 
155  //The 'attrs' field specifies the initial attributes for the file. Default
156  //values will be used for those attributes that are not specified
157  osMemset(&attributes, 0, sizeof(SftpFileAttrs));
158 
159  //Format ATTRS compound data
160  error = sftpFormatAttributes(context->version, &attributes, p, &n);
161  //Any error to report?
162  if(error)
163  return error;
164 
165  //Total length of the packet
166  length += n;
167 
168  //Convert the length field to network byte order
169  header->length = htonl(length);
170 
171  //The packet length does not include the length field itself
172  context->requestLen = length + sizeof(uint32_t);
173  context->requestPos = 0;
174  context->responseLen = 0;
175  context->responsePos = 0;
176 
177  //Save the SFTP packet type
178  context->requestType = (SftpPacketType) header->type;
179 
180  //Debug message
181  TRACE_INFO("Sending SSH_FXP_OPEN packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
182  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
183 
184  //Successful processing
185  return NO_ERROR;
186 }
187 
188 
189 /**
190  * @brief Format SSH_FXP_CLOSE packet
191  * @param[in] context Pointer to the SFTP client context
192  * @param[in] handle File handle returned by SSH_FXP_OPEN or SSH_FXP_OPENDIR
193  * @param[in] handleLen Length of the handle string, in bytes
194  * @return Error code
195  **/
196 
198  const uint8_t *handle, size_t handleLen)
199 {
200  error_t error;
201  size_t n;
202  size_t length;
203  uint8_t *p;
204  SftpPacketHeader *header;
205 
206  //Point to the buffer where to format the packet
207  header = (SftpPacketHeader *) context->buffer;
208 
209  //Set packet type
210  header->type = SSH_FXP_CLOSE;
211  //Total length of the packet
212  length = sizeof(uint8_t);
213 
214  //Point the data payload
215  p = header->payload;
216 
217  //The request identifier is used to match each response with the
218  //corresponding request
219  context->requestId++;
220 
221  //Format request identifier
222  STORE32BE(context->requestId, p);
223 
224  //Point to the next field
225  p += sizeof(uint32_t);
226  length += sizeof(uint32_t);
227 
228  //The handle field is a handle previously returned in the response to
229  //SSH_FXP_OPEN or SSH_FXP_OPENDIR
230  error = sshFormatBinaryString(handle, handleLen, p, &n);
231  //Any error to report?
232  if(error)
233  return error;
234 
235  //Total length of the packet
236  length += n;
237 
238  //Convert the length field to network byte order
239  header->length = htonl(length);
240 
241  //The packet length does not include the length field itself
242  context->requestLen = length + sizeof(uint32_t);
243  context->requestPos = 0;
244  context->responseLen = 0;
245  context->responsePos = 0;
246 
247  //Save the SFTP packet type
248  context->requestType = (SftpPacketType) header->type;
249 
250  //Debug message
251  TRACE_INFO("Sending SSH_FXP_CLOSE packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
252  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
253 
254  //Successful processing
255  return NO_ERROR;
256 }
257 
258 
259 /**
260  * @brief Format SSH_FXP_READ packet
261  * @param[in] context Pointer to the SFTP client context
262  * @param[in] handle File handle returned by SSH_FXP_OPEN
263  * @param[in] handleLen Length of the handle string, in bytes
264  * @param[in] offset Offset relative to the beginning of the file from where
265  * to start reading
266  * @param[in] dataLen Maximum number of bytes to read
267  * @return Error code
268  **/
269 
271  const uint8_t *handle, size_t handleLen, uint64_t offset, uint32_t dataLen)
272 {
273  error_t error;
274  size_t n;
275  size_t length;
276  uint8_t *p;
277  SftpPacketHeader *header;
278 
279  //Point to the buffer where to format the packet
280  header = (SftpPacketHeader *) context->buffer;
281 
282  //Set packet type
283  header->type = SSH_FXP_READ;
284  //Total length of the packet
285  length = sizeof(uint8_t);
286 
287  //Point the data payload
288  p = header->payload;
289 
290  //The request identifier is used to match each response with the
291  //corresponding request
292  context->requestId++;
293 
294  //Format request identifier
295  STORE32BE(context->requestId, p);
296 
297  //Point to the next field
298  p += sizeof(uint32_t);
299  length += sizeof(uint32_t);
300 
301  //The handle field is a handle previously returned in the response to
302  //SSH_FXP_OPEN
303  error = sshFormatBinaryString(handle, handleLen, p, &n);
304  //Any error to report?
305  if(error)
306  return error;
307 
308  //Point to the next field
309  p += n;
310  length += n;
311 
312  //The 'offset' field is the offset relative to the beginning of the file
313  //from where to start reading
314  STORE64BE(offset, p);
315 
316  //Point to the next field
317  p += sizeof(uint64_t);
318  length += sizeof(uint64_t);
319 
320  //The 'len' field is the maximum number of bytes to read
321  STORE32BE(dataLen, p);
322 
323  //Total length of the packet
324  length += sizeof(uint32_t);
325 
326  //Convert the length field to network byte order
327  header->length = htonl(length);
328 
329  //The packet length does not include the length field itself
330  context->requestLen = length + sizeof(uint32_t);
331  context->requestPos = 0;
332  context->responseLen = 0;
333  context->responsePos = 0;
334 
335  //Save the number of data bytes requested in the SSH_FXP_READ packet
336  context->dataLen = dataLen;
337  //Save the SFTP packet type
338  context->requestType = (SftpPacketType) header->type;
339 
340  //Debug message
341  TRACE_INFO("Sending SSH_FXP_READ packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
342  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
343 
344  //Successful processing
345  return NO_ERROR;
346 }
347 
348 
349 /**
350  * @brief Format SSH_FXP_WRITE packet
351  * @param[in] context Pointer to the SFTP client context
352  * @param[in] handle File handle returned by SSH_FXP_OPEN
353  * @param[in] handleLen Length of the handle string, in bytes
354  * @param[in] offset Offset relative to the beginning of the file from where
355  * to start writing
356  * @param[in] dataLen Length of the data to be written
357  * @return Error code
358  **/
359 
361  const uint8_t *handle, size_t handleLen, uint64_t offset, uint32_t dataLen)
362 {
363  error_t error;
364  size_t n;
365  size_t length;
366  uint8_t *p;
367  SftpPacketHeader *header;
368 
369  //Point to the buffer where to format the packet
370  header = (SftpPacketHeader *) context->buffer;
371 
372  //Set packet type
373  header->type = SSH_FXP_WRITE;
374  //Total length of the packet
375  length = sizeof(uint8_t);
376 
377  //Point the data payload
378  p = header->payload;
379 
380  //The request identifier is used to match each response with the
381  //corresponding request
382  context->requestId++;
383 
384  //Format request identifier
385  STORE32BE(context->requestId, p);
386 
387  //Point to the next field
388  p += sizeof(uint32_t);
389  length += sizeof(uint32_t);
390 
391  //The handle field is a handle previously returned in the response to
392  //SSH_FXP_OPEN
393  error = sshFormatBinaryString(handle, handleLen, p, &n);
394  //Any error to report?
395  if(error)
396  return error;
397 
398  //Point to the next field
399  p += n;
400  length += n;
401 
402  //The 'offset' field is the offset relative to the beginning of the file
403  //from where to start writing
404  STORE64BE(offset, p);
405 
406  //Point to the next field
407  p += sizeof(uint64_t);
408  length += sizeof(uint64_t);
409 
410  //The 'data' field contains the data to be written
411  STORE32BE(dataLen, p);
412 
413  //Total length of the packet
414  length += sizeof(uint32_t);
415 
416  //Convert the length field to network byte order
417  header->length = htonl(length + dataLen);
418 
419  //The packet length does not include the length field itself
420  context->requestLen = length + sizeof(uint32_t);
421  context->requestPos = 0;
422  context->responseLen = 0;
423  context->responsePos = 0;
424 
425  //Save the number of data bytes to be written
426  context->dataLen = dataLen;
427  //Save the SFTP packet type
428  context->requestType = (SftpPacketType) header->type;
429 
430  //Debug message
431  TRACE_INFO("Sending SSH_FXP_WRITE packet (%" PRIuSIZE " bytes)...\r\n",
432  (size_t) (context->requestLen + dataLen));
433  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
434 
435  //Successful processing
436  return NO_ERROR;
437 }
438 
439 
440 /**
441  * @brief Format SSH_FXP_OPENDIR packet
442  * @param[in] context Pointer to the SFTP client context
443  * @param[in] path Path name of the directory to be listed
444  * @return Error code
445  **/
446 
448  const char_t *path)
449 {
450  error_t error;
451  size_t n;
452  size_t length;
453  uint8_t *p;
454  SftpPacketHeader *header;
455 
456  //Point to the buffer where to format the packet
457  header = (SftpPacketHeader *) context->buffer;
458 
459  //Set packet type
460  header->type = SSH_FXP_OPENDIR;
461  //Total length of the packet
462  length = sizeof(uint8_t);
463 
464  //Point the data payload
465  p = header->payload;
466 
467  //The request identifier is used to match each response with the
468  //corresponding request
469  context->requestId++;
470 
471  //Format request identifier
472  STORE32BE(context->requestId, p);
473 
474  //Point to the next field
475  p += sizeof(uint32_t);
476  length += sizeof(uint32_t);
477 
478  //The path field specifies the directory to be listed
479  error = sftpFormatPath(context, path, p, &n);
480  //Any error to report?
481  if(error)
482  return error;
483 
484  //Total length of the packet
485  length += n;
486 
487  //Convert the length field to network byte order
488  header->length = htonl(length);
489 
490  //The packet length does not include the length field itself
491  context->requestLen = length + sizeof(uint32_t);
492  context->requestPos = 0;
493  context->responseLen = 0;
494  context->responsePos = 0;
495 
496  //Save the SFTP packet type
497  context->requestType = (SftpPacketType) header->type;
498 
499  //Debug message
500  TRACE_INFO("Sending SSH_FXP_OPENDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
501  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
502 
503  //Successful processing
504  return NO_ERROR;
505 }
506 
507 
508 /**
509  * @brief Format SSH_FXP_READDIR packet
510  * @param[in] context Pointer to the SFTP client context
511  * @param[in] handle File handle returned by SSH_FXP_OPENDIR
512  * @param[in] handleLen Length of the handle string, in bytes
513  * @return Error code
514  **/
515 
517  const uint8_t *handle, size_t handleLen)
518 {
519  error_t error;
520  size_t n;
521  size_t length;
522  uint8_t *p;
523  SftpPacketHeader *header;
524 
525  //Point to the buffer where to format the packet
526  header = (SftpPacketHeader *) context->buffer;
527 
528  //Set packet type
529  header->type = SSH_FXP_READDIR;
530  //Total length of the packet
531  length = sizeof(uint8_t);
532 
533  //Point the data payload
534  p = header->payload;
535 
536  //The request identifier is used to match each response with the
537  //corresponding request
538  context->requestId++;
539 
540  //Format request identifier
541  STORE32BE(context->requestId, p);
542 
543  //Point to the next field
544  p += sizeof(uint32_t);
545  length += sizeof(uint32_t);
546 
547  //The handle field is a handle previously returned in the response to
548  //SSH_FXP_OPENDIR
549  error = sshFormatBinaryString(handle, handleLen, p, &n);
550  //Any error to report?
551  if(error)
552  return error;
553 
554  //Total length of the packet
555  length += n;
556 
557  //Convert the length field to network byte order
558  header->length = htonl(length);
559 
560  //The packet length does not include the length field itself
561  context->requestLen = length + sizeof(uint32_t);
562  context->requestPos = 0;
563  context->responseLen = 0;
564  context->responsePos = 0;
565 
566  //Save the SFTP packet type
567  context->requestType = (SftpPacketType) header->type;
568 
569  //Debug message
570  TRACE_INFO("Sending SSH_FXP_READDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
571  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
572 
573  //Successful processing
574  return NO_ERROR;
575 }
576 
577 
578 /**
579  * @brief Format SSH_FXP_REMOVE packet
580  * @param[in] context Pointer to the SFTP client context
581  * @param[in] filename Name of the file to be removed
582  * @return Error code
583  **/
584 
586  const char_t *filename)
587 {
588  error_t error;
589  size_t n;
590  size_t length;
591  uint8_t *p;
592  SftpPacketHeader *header;
593 
594  //Point to the buffer where to format the packet
595  header = (SftpPacketHeader *) context->buffer;
596 
597  //Set packet type
598  header->type = SSH_FXP_REMOVE;
599  //Total length of the packet
600  length = sizeof(uint8_t);
601 
602  //Point the data payload
603  p = header->payload;
604 
605  //The request identifier is used to match each response with the
606  //corresponding request
607  context->requestId++;
608 
609  //Format request identifier
610  STORE32BE(context->requestId, p);
611 
612  //Point to the next field
613  p += sizeof(uint32_t);
614  length += sizeof(uint32_t);
615 
616  //The filename field specifies the file to be removed
617  error = sftpFormatPath(context, filename, p, &n);
618  //Any error to report?
619  if(error)
620  return error;
621 
622  //Total length of the packet
623  length += n;
624 
625  //Convert the length field to network byte order
626  header->length = htonl(length);
627 
628  //The packet length does not include the length field itself
629  context->requestLen = length + sizeof(uint32_t);
630  context->requestPos = 0;
631  context->responseLen = 0;
632  context->responsePos = 0;
633 
634  //Save the SFTP packet type
635  context->requestType = (SftpPacketType) header->type;
636 
637  //Debug message
638  TRACE_INFO("Sending SSH_FXP_REMOVE packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
639  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
640 
641  //Successful processing
642  return NO_ERROR;
643 }
644 
645 
646 /**
647  * @brief Format SSH_FXP_MKDIR packet
648  * @param[in] context Pointer to the SFTP client context
649  * @param[in] path Directory to be created
650  * @return Error code
651  **/
652 
654  const char_t *path)
655 {
656  error_t error;
657  size_t n;
658  size_t length;
659  uint8_t *p;
660  SftpPacketHeader *header;
662 
663  //Point to the buffer where to format the packet
664  header = (SftpPacketHeader *) context->buffer;
665 
666  //Set packet type
667  header->type = SSH_FXP_MKDIR;
668  //Total length of the packet
669  length = sizeof(uint8_t);
670 
671  //Point the data payload
672  p = header->payload;
673 
674  //The request identifier is used to match each response with the
675  //corresponding request
676  context->requestId++;
677 
678  //Format request identifier
679  STORE32BE(context->requestId, p);
680 
681  //Point to the next field
682  p += sizeof(uint32_t);
683  length += sizeof(uint32_t);
684 
685  //The path field specifies the directory to be created
686  error = sftpFormatPath(context, path, p, &n);
687  //Any error to report?
688  if(error)
689  return error;
690 
691  //Point to the next field
692  p += n;
693  length += n;
694 
695  //The 'attrs' field specifies the modifications to be made to its attributes
696  osMemset(&attributes, 0, sizeof(SftpFileAttrs));
697 
698  //Format ATTRS compound data
699  error = sftpFormatAttributes(context->version, &attributes, p, &n);
700  //Any error to report?
701  if(error)
702  return error;
703 
704  //Total length of the packet
705  length += n;
706 
707  //Convert the length field to network byte order
708  header->length = htonl(length);
709 
710  //The packet length does not include the length field itself
711  context->requestLen = length + sizeof(uint32_t);
712  context->requestPos = 0;
713  context->responseLen = 0;
714  context->responsePos = 0;
715 
716  //Save the SFTP packet type
717  context->requestType = (SftpPacketType) header->type;
718 
719  //Debug message
720  TRACE_INFO("Sending SSH_FXP_MKDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
721  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
722 
723  //Successful processing
724  return NO_ERROR;
725 }
726 
727 
728 /**
729  * @brief Format SSH_FXP_RMDIR packet
730  * @param[in] context Pointer to the SFTP client context
731  * @param[in] path Directory to be removed
732  * @return Error code
733  **/
734 
736  const char_t *path)
737 {
738  error_t error;
739  size_t n;
740  size_t length;
741  uint8_t *p;
742  SftpPacketHeader *header;
743 
744  //Point to the buffer where to format the packet
745  header = (SftpPacketHeader *) context->buffer;
746 
747  //Set packet type
748  header->type = SSH_FXP_RMDIR;
749  //Total length of the packet
750  length = sizeof(uint8_t);
751 
752  //Point the data payload
753  p = header->payload;
754 
755  //The request identifier is used to match each response with the
756  //corresponding request
757  context->requestId++;
758 
759  //Format request identifier
760  STORE32BE(context->requestId, p);
761 
762  //Point to the next field
763  p += sizeof(uint32_t);
764  length += sizeof(uint32_t);
765 
766  //The path field specifies the directory to be removed
767  error = sftpFormatPath(context, path, p, &n);
768  //Any error to report?
769  if(error)
770  return error;
771 
772  //Total length of the packet
773  length += n;
774 
775  //Convert the length field to network byte order
776  header->length = htonl(length);
777 
778  //The packet length does not include the length field itself
779  context->requestLen = length + sizeof(uint32_t);
780  context->requestPos = 0;
781  context->responseLen = 0;
782  context->responsePos = 0;
783 
784  //Save the SFTP packet type
785  context->requestType = (SftpPacketType) header->type;
786 
787  //Debug message
788  TRACE_INFO("Sending SSH_FXP_RMDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
789  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
790 
791  //Successful processing
792  return NO_ERROR;
793 }
794 
795 
796 /**
797  * @brief Format SSH_FXP_REALPATH packet
798  * @param[in] context Pointer to the SFTP client context
799  * @param[in] path Path name to be canonicalized
800  * @return Error code
801  **/
802 
804  const char_t *path)
805 {
806  error_t error;
807  size_t n;
808  size_t length;
809  uint8_t *p;
810  SftpPacketHeader *header;
811 
812  //Point to the buffer where to format the packet
813  header = (SftpPacketHeader *) context->buffer;
814 
815  //Set packet type
816  header->type = SSH_FXP_REALPATH;
817  //Total length of the packet
818  length = sizeof(uint8_t);
819 
820  //Point the data payload
821  p = header->payload;
822 
823  //The request identifier is used to match each response with the
824  //corresponding request
825  context->requestId++;
826 
827  //Format request identifier
828  STORE32BE(context->requestId, p);
829 
830  //Point to the next field
831  p += sizeof(uint32_t);
832  length += sizeof(uint32_t);
833 
834  //The path field specifies the path name to be canonicalized
835  error = sshFormatString(path, p, &n);
836  //Any error to report?
837  if(error)
838  return error;
839 
840  //Total length of the packet
841  length += n;
842 
843  //Convert the length field to network byte order
844  header->length = htonl(length);
845 
846  //The packet length does not include the length field itself
847  context->requestLen = length + sizeof(uint32_t);
848  context->requestPos = 0;
849  context->responseLen = 0;
850  context->responsePos = 0;
851 
852  //Save the SFTP packet type
853  context->requestType = (SftpPacketType) header->type;
854 
855  //Debug message
856  TRACE_INFO("Sending SSH_FXP_REALPATH packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
857  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
858 
859  //Successful processing
860  return NO_ERROR;
861 }
862 
863 
864 /**
865  * @brief Format SSH_FXP_STAT packet
866  * @param[in] context Pointer to the SFTP client context
867  * @param[in] path File system object for which status is to be returned
868  * @return Error code
869  **/
870 
872  const char_t *path)
873 {
874  error_t error;
875  size_t n;
876  size_t length;
877  uint8_t *p;
878  SftpPacketHeader *header;
879 
880  //Point to the buffer where to format the packet
881  header = (SftpPacketHeader *) context->buffer;
882 
883  //Set packet type
884  header->type = SSH_FXP_STAT;
885  //Total length of the packet
886  length = sizeof(uint8_t);
887 
888  //Point the data payload
889  p = header->payload;
890 
891  //The request identifier is used to match each response with the
892  //corresponding request
893  context->requestId++;
894 
895  //Format request identifier
896  STORE32BE(context->requestId, p);
897 
898  //Point to the next field
899  p += sizeof(uint32_t);
900  length += sizeof(uint32_t);
901 
902  //The path field specifies the file system object for which status is to be
903  //returned
904  error = sftpFormatPath(context, path, p, &n);
905  //Any error to report?
906  if(error)
907  return error;
908 
909  //Total length of the packet
910  length += n;
911 
912  //Convert the length field to network byte order
913  header->length = htonl(length);
914 
915  //The packet length does not include the length field itself
916  context->requestLen = length + sizeof(uint32_t);
917  context->requestPos = 0;
918  context->responseLen = 0;
919  context->responsePos = 0;
920 
921  //Save the SFTP packet type
922  context->requestType = (SftpPacketType) header->type;
923 
924  //Debug message
925  TRACE_INFO("Sending SSH_FXP_STAT packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
926  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
927 
928  //Successful processing
929  return NO_ERROR;
930 }
931 
932 
933 /**
934  * @brief Format SSH_FXP_RENAME packet
935  * @param[in] context Pointer to the SFTP client context
936  * @param[in] oldPath Name of an existing file or directory
937  * @param[in] newPath New name for the file or directory
938  * @return Error code
939  **/
940 
942  const char_t *oldPath, const char_t *newPath)
943 {
944  error_t error;
945  size_t n;
946  size_t length;
947  uint8_t *p;
948  SftpPacketHeader *header;
949 
950  //Point to the buffer where to format the packet
951  header = (SftpPacketHeader *) context->buffer;
952 
953  //Set packet type
954  header->type = SSH_FXP_RENAME;
955  //Total length of the packet
956  length = sizeof(uint8_t);
957 
958  //Point the data payload
959  p = header->payload;
960 
961  //The request identifier is used to match each response with the
962  //corresponding request
963  context->requestId++;
964 
965  //Format request identifier
966  STORE32BE(context->requestId, p);
967 
968  //Point to the next field
969  p += sizeof(uint32_t);
970  length += sizeof(uint32_t);
971 
972  //The oldpath field is the name of an existing file or directory
973  error = sftpFormatPath(context, oldPath, p, &n);
974  //Any error to report?
975  if(error)
976  return error;
977 
978  //Point to the next field
979  p += n;
980  length += n;
981 
982  //The newpath field is the new name for the file or directory
983  error = sftpFormatPath(context, newPath, p, &n);
984  //Any error to report?
985  if(error)
986  return error;
987 
988  //Total length of the packet
989  length += n;
990 
991  //Convert the length field to network byte order
992  header->length = htonl(length);
993 
994  //The packet length does not include the length field itself
995  context->requestLen = length + sizeof(uint32_t);
996  context->requestPos = 0;
997  context->responseLen = 0;
998  context->responsePos = 0;
999 
1000  //Save the SFTP packet type
1001  context->requestType = (SftpPacketType) header->type;
1002 
1003  //Debug message
1004  TRACE_INFO("Sending SSH_FXP_RENAME packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
1005  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
1006 
1007  //Successful processing
1008  return NO_ERROR;
1009 }
1010 
1011 
1012 /**
1013  * @brief Parse SSH_FXP_VERSION packet
1014  * @param[in] context Pointer to the SFTP client context
1015  * @param[in] packet Pointer to packet
1016  * @param[in] length Length of the packet, in bytes
1017  * @return Error code
1018  **/
1019 
1021  const uint8_t *packet, size_t length)
1022 {
1023  error_t error;
1024  uint32_t version;
1025  const uint8_t *p;
1026  SshString extensionName;
1027  SshString extensionValue;
1028 
1029  //Debug message
1030  TRACE_INFO("SSH_FXP_VERSION packet received (%" PRIuSIZE " bytes)...\r\n", length);
1031  TRACE_VERBOSE_ARRAY(" ", packet, length);
1032 
1033  //An SSH_FXP_VERSION packet is sent in response to an SSH_FXP_INIT request
1034  if(context->requestType != SSH_FXP_INIT)
1035  return ERROR_INVALID_TYPE;
1036 
1037  //Point to the first field of the packet
1038  p = packet;
1039 
1040  //Malformed packet?
1041  if(length < sizeof(uint32_t))
1042  return ERROR_INVALID_PACKET;
1043 
1044  //The SSH_FXP_VERSION packet contains the lowest of its own and the
1045  //client's version number
1046  version = LOAD32BE(p);
1047 
1048  //Point to the next field
1049  p += sizeof(uint32_t);
1050  length -= sizeof(uint32_t);
1051 
1052  //Parse extensions
1053  while(length > 0)
1054  {
1055  //Decode extension name
1056  error = sshParseString(p, length, &extensionName);
1057  //Any error to report?
1058  if(error)
1059  return error;
1060 
1061  //Point to the next field
1062  p += sizeof(uint32_t) + extensionName.length;
1063  length -= sizeof(uint32_t) + extensionName.length;
1064 
1065  //Decode extension value
1066  error = sshParseString(p, length, &extensionValue);
1067  //Any error to report?
1068  if(error)
1069  return error;
1070 
1071  //Point to the next field
1072  p += sizeof(uint32_t) + extensionValue.length;
1073  length -= sizeof(uint32_t) + extensionValue.length;
1074  }
1075 
1076  //Sanity check
1077  if(version < SFTP_CLIENT_MIN_VERSION || version > SFTP_CLIENT_MAX_VERSION)
1078  return ERROR_INVALID_VERSION;
1079 
1080  //From then on, both parties must use the same version of the protocol
1081  context->version = (SftpVersion) version;
1082 
1083  //Successful processing
1084  return NO_ERROR;
1085 }
1086 
1087 
1088 /**
1089  * @brief Parse SSH_FXP_STATUS packet
1090  * @param[in] context Pointer to the SFTP client context
1091  * @param[in] packet Pointer to packet
1092  * @param[in] length Length of the packet, in bytes
1093  * @return Error code
1094  **/
1095 
1097  const uint8_t *packet, size_t length)
1098 {
1099  error_t error;
1100  uint32_t id;
1101  const uint8_t *p;
1102  SshString errorMessage;
1103  SshString languageTag;
1104 
1105  //Debug message
1106  TRACE_INFO("SSH_FXP_STATUS packet received (%" PRIuSIZE " bytes)...\r\n", length);
1107  TRACE_VERBOSE_ARRAY(" ", packet, length);
1108 
1109  //All requests can return an SSH_FXP_STATUS response upon failure
1110  if(context->requestType == SSH_FXP_INIT)
1111  return ERROR_INVALID_TYPE;
1112 
1113  //Point to the first field of the packet
1114  p = packet;
1115 
1116  //Malformed packet?
1117  if(length < sizeof(uint32_t))
1118  return ERROR_INVALID_PACKET;
1119 
1120  //Each response packet begins with the request identifier
1121  id = LOAD32BE(p);
1122 
1123  //The request identifier is used to match each response with the
1124  //corresponding request
1125  if(id != context->requestId)
1126  return ERROR_WRONG_IDENTIFIER;
1127 
1128  //Point to the next field
1129  p += sizeof(uint32_t);
1130  length -= sizeof(uint32_t);
1131 
1132  //Malformed packet?
1133  if(length < sizeof(uint32_t))
1134  return ERROR_INVALID_PACKET;
1135 
1136  //The status code indicates the result of the requested operation
1137  context->statusCode = LOAD32BE(p);
1138 
1139  //Point to the next field
1140  p += sizeof(uint32_t);
1141  length -= sizeof(uint32_t);
1142 
1143  //In version 3, the SSH_FXP_STATUS message was changed to include fields
1144  //'error message' and 'language tag'
1145  if(context->version >= SFTP_VERSION_3)
1146  {
1147  //Decode description string
1148  error = sshParseString(p, length, &errorMessage);
1149  //Any error to report?
1150  if(error)
1151  return error;
1152 
1153  //Point to the next field
1154  p += sizeof(uint32_t) + errorMessage.length;
1155  length -= sizeof(uint32_t) + errorMessage.length;
1156 
1157  //Decode language tag
1158  error = sshParseString(p, length, &languageTag);
1159  //Any error to report?
1160  if(error)
1161  return error;
1162 
1163  //Point to the next field
1164  p += sizeof(uint32_t) + languageTag.length;
1165  length -= sizeof(uint32_t) + languageTag.length;
1166  }
1167 
1168  //Malformed message?
1169  if(length != 0)
1170  return ERROR_INVALID_MESSAGE;
1171 
1172  //Check the result of the requested operation
1173  if(context->statusCode == SSH_FX_OK)
1174  {
1175  //If no data needs to be returned to the client, the SSH_FXP_STATUS
1176  //response with SSH_FX_OK status is appropriate
1177  if(context->requestType == SSH_FXP_CLOSE ||
1178  context->requestType == SSH_FXP_WRITE ||
1179  context->requestType == SSH_FXP_SETSTAT ||
1180  context->requestType == SSH_FXP_FSETSTAT ||
1181  context->requestType == SSH_FXP_REMOVE ||
1182  context->requestType == SSH_FXP_MKDIR ||
1183  context->requestType == SSH_FXP_RMDIR ||
1184  context->requestType == SSH_FXP_RENAME ||
1185  context->requestType == SSH_FXP_SYMLINK)
1186  {
1187  //The value SSH_FX_OK indicates success
1188  error = NO_ERROR;
1189  }
1190  else
1191  {
1192  //Unexpected SSH_FXP_STATUS packet
1193  error = ERROR_INVALID_TYPE;
1194  }
1195  }
1196  else
1197  {
1198  //All other values indicate failure
1199  error = ERROR_UNEXPECTED_RESPONSE;
1200  }
1201 
1202  //Return status code
1203  return error;
1204 }
1205 
1206 
1207 /**
1208  * @brief Parse SSH_FXP_HANDLE packet
1209  * @param[in] context Pointer to the SFTP client context
1210  * @param[in] packet Pointer to packet
1211  * @param[in] length Length of the packet, in bytes
1212  * @return Error code
1213  **/
1214 
1216  const uint8_t *packet, size_t length)
1217 {
1218  error_t error;
1219  uint32_t id;
1220  const uint8_t *p;
1221  SshBinaryString handle;
1222 
1223  //Debug message
1224  TRACE_INFO("SSH_FXP_HANDLE packet received (%" PRIuSIZE " bytes)...\r\n", length);
1225  TRACE_VERBOSE_ARRAY(" ", packet, length);
1226 
1227  //The SSH_FXP_HANDLE message is used to return a file handle (for
1228  //SSH_FXP_OPEN and SSH_FXP_OPENDIR requests)
1229  if(context->requestType != SSH_FXP_OPEN &&
1230  context->requestType != SSH_FXP_OPENDIR)
1231  {
1232  return ERROR_INVALID_TYPE;
1233  }
1234 
1235  //Point to the first field of the packet
1236  p = packet;
1237 
1238  //Malformed packet?
1239  if(length < sizeof(uint32_t))
1240  return ERROR_INVALID_PACKET;
1241 
1242  //Each response packet begins with the request identifier
1243  id = LOAD32BE(p);
1244 
1245  //The request identifier is used to match each response with the
1246  //corresponding request
1247  if(id != context->requestId)
1248  return ERROR_WRONG_IDENTIFIER;
1249 
1250  //Point to the next field
1251  p += sizeof(uint32_t);
1252  length -= sizeof(uint32_t);
1253 
1254  //The handle field is an arbitrary string that identifies a file or
1255  //directory on the server
1256  error = sshParseBinaryString(p, length, &handle);
1257  //Any error to report?
1258  if(error)
1259  return error;
1260 
1261  //Point to the next field
1262  p += sizeof(uint32_t) + handle.length;
1263  length -= sizeof(uint32_t) + handle.length;
1264 
1265  //Malformed message?
1266  if(length != 0)
1267  return ERROR_INVALID_PACKET;
1268 
1269  //The length of the handle string must not exceed 256 data bytes
1270  if(handle.length > SFTP_CLIENT_MAX_HANDLE_SIZE)
1271  return ERROR_INVALID_HANDLE;
1272 
1273  //The handle is opaque to the client. The client must not attempt to
1274  //interpret or modify it in any way
1275  osMemcpy(context->handle, handle.value, handle.length);
1276 
1277  //Save the length of the handle string
1278  context->handleLen = handle.length;
1279 
1280  //Successful processing
1281  return NO_ERROR;
1282 }
1283 
1284 
1285 /**
1286  * @brief Parse SSH_FXP_DATA packet
1287  * @param[in] context Pointer to the SFTP client context
1288  * @param[in] packet Pointer to packet
1289  * @param[in] fragLen Number of bytes available on hand
1290  * @param[in] totalLen Total length of the packet, in bytes
1291  * @return Error code
1292  **/
1293 
1295  const uint8_t *packet, size_t fragLen, size_t totalLen)
1296 {
1297  error_t error;
1298  uint32_t id;
1299  const uint8_t *p;
1301 
1302  //Debug message
1303  TRACE_INFO("SSH_FXP_DATA packet received (%" PRIuSIZE " bytes)...\r\n", totalLen);
1304  TRACE_VERBOSE_ARRAY(" ", packet, fragLen);
1305 
1306  //Sanity check
1307  if(fragLen != sizeof(SftpFxpDataHeader))
1308  return ERROR_INVALID_PACKET;
1309 
1310  //SSH_FXP_DATA is used to return data from SSH_FXP_READ
1311  if(context->requestType != SSH_FXP_READ)
1312  return ERROR_INVALID_TYPE;
1313 
1314  //Point to the first field of the packet
1315  p = packet;
1316 
1317  //Malformed packet?
1318  if(totalLen < sizeof(uint32_t))
1319  return ERROR_INVALID_PACKET;
1320 
1321  //Each response packet begins with the request identifier
1322  id = LOAD32BE(p);
1323 
1324  //The request identifier is used to match each response with the
1325  //corresponding request
1326  if(id != context->requestId)
1327  return ERROR_WRONG_IDENTIFIER;
1328 
1329  //Point to the next field
1330  p += sizeof(uint32_t);
1331  totalLen -= sizeof(uint32_t);
1332 
1333  //The data field is a byte string containing the requested data
1334  error = sshParseBinaryString(p, totalLen, &data);
1335  //Any error to report?
1336  if(error)
1337  return error;
1338 
1339  //Point to the data payload
1340  p += sizeof(uint32_t);
1341  totalLen -= sizeof(uint32_t);
1342 
1343  //Malformed packet?
1344  if(data.length != totalLen)
1345  return ERROR_INVALID_PACKET;
1346 
1347  //The data string may be at most the number of bytes requested in a
1348  //SSH_FXP_READ request, but may also be shorter if end of file is reached
1349  if(data.length > context->dataLen)
1350  return ERROR_INVALID_LENGTH;
1351 
1352  //Save the actual number of data bytes in the SSH_FXP_DATA response
1353  context->dataLen = data.length;
1354 
1355  //Successful processing
1356  return NO_ERROR;
1357 }
1358 
1359 
1360 /**
1361  * @brief Parse SSH_FXP_NAME packet
1362  * @param[in] context Pointer to the SFTP client context
1363  * @param[in] packet Pointer to packet
1364  * @param[in] fragLen Number of bytes available on hand
1365  * @param[in] totalLen Total length of the packet, in bytes
1366  * @return Error code
1367  **/
1368 
1370  const uint8_t *packet, size_t fragLen, size_t totalLen)
1371 {
1372  error_t error;
1373  size_t n;
1374  uint32_t id;
1375  uint32_t count;
1376  SftpName name;
1377  const uint8_t *p;
1378 
1379  //Debug message
1380  TRACE_INFO("SSH_FXP_NAME packet received (%" PRIuSIZE " bytes)...\r\n", totalLen);
1381  TRACE_VERBOSE_ARRAY(" ", packet, fragLen);
1382 
1383  //SSH_FXP_NAME is used to return one or more file names from an SSH_FXP_READDIR
1384  //or SSH_FXP_REALPATH request
1385  if(context->requestType != SSH_FXP_READDIR &&
1386  context->requestType != SSH_FXP_REALPATH)
1387  {
1388  return ERROR_INVALID_TYPE;
1389  }
1390 
1391  //Point to the first field of the packet
1392  p = packet;
1393 
1394  //Malformed packet?
1395  if(fragLen < sizeof(uint32_t) || fragLen > totalLen)
1396  return ERROR_INVALID_PACKET;
1397 
1398  //Each response packet begins with the request identifier
1399  id = LOAD32BE(p);
1400 
1401  //The request identifier is used to match each response with the
1402  //corresponding request
1403  if(id != context->requestId)
1404  return ERROR_WRONG_IDENTIFIER;
1405 
1406  //Point to the next field
1407  p += sizeof(uint32_t);
1408  fragLen -= sizeof(uint32_t);
1409  totalLen -= sizeof(uint32_t);
1410 
1411  //Malformed packet?
1412  if(fragLen < sizeof(uint32_t))
1413  return ERROR_INVALID_PACKET;
1414 
1415  //Get the number of names returned in this response
1416  count = LOAD32BE(p);
1417 
1418  //Point to the next field
1419  p += sizeof(uint32_t);
1420  fragLen -= sizeof(uint32_t);
1421  totalLen -= sizeof(uint32_t);
1422 
1423  //SSH_FXP_READDIR or SSH_FXP_REALPATH request?
1424  if(context->requestType == SSH_FXP_READDIR)
1425  {
1426  //Each SSH_FXP_READDIR request returns one or more file names with full
1427  //file attributes for each file
1428  if(count < 1)
1429  return ERROR_INVALID_PACKET;
1430  }
1431  else
1432  {
1433  //The server will respond to an SSH_FXP_REALPATH request with an SSH_FXP_NAME
1434  //packet containing only one name and a dummy attributes value
1435  if(count != 1)
1436  return ERROR_INVALID_PACKET;
1437 
1438  //Parse file name and attributes
1439  error = sftpParseName(context->version, &name, p, fragLen, &n);
1440  //Any error to report?
1441  if(error)
1442  return error;
1443 
1444  //Malformed packet?
1445  if(fragLen != n || totalLen != n)
1446  return ERROR_INVALID_PACKET;
1447  }
1448 
1449  //Move the remaining data bytes to the start of the buffer
1450  osMemmove(context->buffer, p, fragLen);
1451 
1452  //Number of data bytes left to process
1453  context->dataLen = totalLen;
1454  context->responseLen = fragLen;
1455  context->responsePos = 0;
1456 
1457  //Successful processing
1458  return NO_ERROR;
1459 }
1460 
1461 
1462 /**
1463  * @brief Parse SSH_FXP_ATTRS packet
1464  * @param[in] context Pointer to the SFTP client context
1465  * @param[in] packet Pointer to packet
1466  * @param[in] length Length of the packet, in bytes
1467  * @return Error code
1468  **/
1469 
1471  const uint8_t *packet, size_t length)
1472 {
1473  error_t error;
1474  size_t n;
1475  uint32_t id;
1476  const uint8_t *p;
1478 
1479  //Debug message
1480  TRACE_INFO("SSH_FXP_ATTRS packet received (%" PRIuSIZE " bytes)...\r\n", length);
1481  TRACE_VERBOSE_ARRAY(" ", packet, length);
1482 
1483  //SSH_FXP_ATTRS is used to return file attributes from SSH_FXP_STAT,
1484  //SSH_FXP_LSTAT, and SSH_FXP_FSTAT requests
1485  if(context->requestType != SSH_FXP_STAT &&
1486  context->requestType != SSH_FXP_LSTAT &&
1487  context->requestType != SSH_FXP_FSTAT)
1488  {
1489  return ERROR_INVALID_TYPE;
1490  }
1491 
1492  //Point to the first field of the packet
1493  p = packet;
1494 
1495  //Malformed packet?
1496  if(length < sizeof(uint32_t))
1497  return ERROR_INVALID_PACKET;
1498 
1499  //Each response packet begins with the request identifier
1500  id = LOAD32BE(p);
1501 
1502  //The request identifier is used to match each response with the
1503  //corresponding request
1504  if(id != context->requestId)
1505  return ERROR_WRONG_IDENTIFIER;
1506 
1507  //Point to the next field
1508  p += sizeof(uint32_t);
1509  length -= sizeof(uint32_t);
1510 
1511  //Parse ATTRS compound data
1512  error = sftpParseAttributes(context->version, &attributes, p, length, &n);
1513  //Any error to report?
1514  if(error)
1515  return error;
1516 
1517  //Malformed packet?
1518  if(length != n)
1519  return ERROR_INVALID_PACKET;
1520 
1521  //Move the remaining data bytes to the start of the buffer
1522  osMemmove(context->buffer, p, length);
1523 
1524  //Number of data bytes left to process
1525  context->dataLen = length;
1526  context->responseLen = length;
1527  context->responsePos = 0;
1528 
1529  //Successful processing
1530  return NO_ERROR;
1531 }
1532 
1533 #endif
Path manipulation helper functions.
error_t sftpFormatPath(SftpClientContext *context, const char_t *path, uint8_t *p, size_t *written)
Format pathname.
@ SSH_FXP_FSETSTAT
Definition: sftp_common.h:144
error_t sftpClientFormatFxpWrite(SftpClientContext *context, const uint8_t *handle, size_t handleLen, uint64_t offset, uint32_t dataLen)
Format SSH_FXP_WRITE packet.
SftpPacketType
SFTP packet types.
Definition: sftp_common.h:134
SFTP packet parsing and formatting.
#define LOAD32BE(p)
Definition: cpu_endian.h:210
Binary string.
Definition: ssh_types.h:67
error_t sftpClientFormatFxpRename(SftpClientContext *context, const char_t *oldPath, const char_t *newPath)
Format SSH_FXP_RENAME packet.
error_t sftpClientFormatFxpRemove(SftpClientContext *context, const char_t *filename)
Format SSH_FXP_REMOVE packet.
@ SSH_FXP_OPEN
Definition: sftp_common.h:137
uint8_t p
Definition: ndp.h:300
@ SSH_FXP_SETSTAT
Definition: sftp_common.h:143
error_t sftpClientFormatFxpRmDir(SftpClientContext *context, const char_t *path)
Format SSH_FXP_RMDIR packet.
uint8_t data[]
Definition: ethernet.h:224
@ SSH_FXP_REALPATH
Definition: sftp_common.h:150
error_t sftpClientFormatFxpReadDir(SftpClientContext *context, const uint8_t *handle, size_t handleLen)
Format SSH_FXP_READDIR packet.
@ SFTP_VERSION_3
Definition: sftp_common.h:122
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
char_t name[]
size_t length
Definition: ssh_types.h:58
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
uint8_t version
Definition: coap_common.h:177
@ SSH_FXP_WRITE
Definition: sftp_common.h:140
@ ERROR_INVALID_HANDLE
Definition: error.h:282
@ ERROR_INVALID_VERSION
Definition: error.h:118
@ SSH_FXP_READDIR
Definition: sftp_common.h:146
error_t sftpClientParseFxpHandle(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_HANDLE packet.
size_t length
Definition: ssh_types.h:69
error_t sshFormatBinaryString(const void *value, size_t valueLen, uint8_t *p, size_t *written)
Format a binary string.
Definition: ssh_misc.c:1446
error_t sftpClientFormatFxpInit(SftpClientContext *context, uint32_t version)
Format SSH_FXP_INIT packet.
#define htonl(value)
Definition: cpu_endian.h:414
error_t sftpClientFormatFxpRealPath(SftpClientContext *context, const char_t *path)
Format SSH_FXP_REALPATH packet.
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
error_t sftpClientParseFxpName(SftpClientContext *context, const uint8_t *packet, size_t fragLen, size_t totalLen)
Parse SSH_FXP_NAME packet.
error_t
Error codes.
Definition: error.h:43
error_t sftpClientFormatFxpStat(SftpClientContext *context, const char_t *path)
Format SSH_FXP_STAT packet.
error_t sftpClientParseFxpAttrs(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_ATTRS packet.
@ SSH_FXP_RENAME
Definition: sftp_common.h:152
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 sftpParseName(SftpVersion version, SftpName *name, const uint8_t *data, size_t length, size_t *consumed)
Parse name structure.
Definition: sftp_common.c:370
@ SSH_FXP_OPENDIR
Definition: sftp_common.h:145
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
@ SSH_FXP_RMDIR
Definition: sftp_common.h:149
SftpFxpDataHeader
Definition: sftp_common.h:231
@ ERROR_INVALID_PACKET
Definition: error.h:141
@ ERROR_INVALID_LENGTH
Definition: error.h:111
char_t filename[]
Definition: tftp_common.h:93
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ ERROR_UNEXPECTED_RESPONSE
Definition: error.h:70
@ SSH_FXP_SYMLINK
Definition: sftp_common.h:154
@ SSH_FXP_LSTAT
Definition: sftp_common.h:141
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
@ SSH_FX_OK
Definition: sftp_common.h:171
error_t sftpClientFormatFxpOpen(SftpClientContext *context, const char_t *filename, uint32_t pflags)
Format SSH_FXP_OPEN packet.
error_t sftpClientFormatFxpRead(SftpClientContext *context, const uint8_t *handle, size_t handleLen, uint64_t offset, uint32_t dataLen)
Format SSH_FXP_READ packet.
@ SSH_FXP_READ
Definition: sftp_common.h:139
@ SSH_FXP_MKDIR
Definition: sftp_common.h:148
String.
Definition: ssh_types.h:56
uint32_t dataLen
Definition: sftp_common.h:229
#define SFTP_CLIENT_MAX_HANDLE_SIZE
Definition: sftp_client.h:82
@ SSH_FXP_REMOVE
Definition: sftp_common.h:147
error_t sftpClientParseFxpData(SftpClientContext *context, const uint8_t *packet, size_t fragLen, size_t totalLen)
Parse SSH_FXP_DATA packet.
const uint8_t * value
Definition: ssh_types.h:68
Helper functions for SFTP client.
error_t sftpClientParseFxpStatus(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_STATUS packet.
char char_t
Definition: compiler_port.h:55
Name structure.
Definition: sftp_common.h:265
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
@ SSH_FXP_CLOSE
Definition: sftp_common.h:138
uint8_t n
#define SftpClientContext
Definition: sftp_client.h:108
@ SSH_FXP_FSTAT
Definition: sftp_common.h:142
error_t sftpClientFormatFxpMkDir(SftpClientContext *context, const char_t *path)
Format SSH_FXP_MKDIR packet.
SSH helper functions.
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ SSH_FXP_INIT
Definition: sftp_common.h:135
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
error_t sftpClientParseFxpVersion(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_VERSION packet.
#define PRIuSIZE
#define osMemset(p, value, length)
Definition: os_port.h:141
File attributes.
Definition: sftp_common.h:247
Secure Shell (SSH)
@ SSH_FXP_STAT
Definition: sftp_common.h:151
error_t sftpClientFormatFxpOpenDir(SftpClientContext *context, const char_t *path)
Format SSH_FXP_OPENDIR packet.
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:153
#define SFTP_CLIENT_MAX_VERSION
Definition: sftp_client.h:54
error_t sftpClientFormatFxpClose(SftpClientContext *context, const uint8_t *handle, size_t handleLen)
Format SSH_FXP_CLOSE packet.
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:140