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-2024 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.4.0
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", context->requestLen + dataLen);
432  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
433 
434  //Successful processing
435  return NO_ERROR;
436 }
437 
438 
439 /**
440  * @brief Format SSH_FXP_OPENDIR packet
441  * @param[in] context Pointer to the SFTP client context
442  * @param[in] path Path name of the directory to be listed
443  * @return Error code
444  **/
445 
447  const char_t *path)
448 {
449  error_t error;
450  size_t n;
451  size_t length;
452  uint8_t *p;
453  SftpPacketHeader *header;
454 
455  //Point to the buffer where to format the packet
456  header = (SftpPacketHeader *) context->buffer;
457 
458  //Set packet type
459  header->type = SSH_FXP_OPENDIR;
460  //Total length of the packet
461  length = sizeof(uint8_t);
462 
463  //Point the data payload
464  p = header->payload;
465 
466  //The request identifier is used to match each response with the
467  //corresponding request
468  context->requestId++;
469 
470  //Format request identifier
471  STORE32BE(context->requestId, p);
472 
473  //Point to the next field
474  p += sizeof(uint32_t);
475  length += sizeof(uint32_t);
476 
477  //The path field specifies the directory to be listed
478  error = sftpFormatPath(context, path, p, &n);
479  //Any error to report?
480  if(error)
481  return error;
482 
483  //Total length of the packet
484  length += n;
485 
486  //Convert the length field to network byte order
487  header->length = htonl(length);
488 
489  //The packet length does not include the length field itself
490  context->requestLen = length + sizeof(uint32_t);
491  context->requestPos = 0;
492  context->responseLen = 0;
493  context->responsePos = 0;
494 
495  //Save the SFTP packet type
496  context->requestType = (SftpPacketType) header->type;
497 
498  //Debug message
499  TRACE_INFO("Sending SSH_FXP_OPENDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
500  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
501 
502  //Successful processing
503  return NO_ERROR;
504 }
505 
506 
507 /**
508  * @brief Format SSH_FXP_READDIR packet
509  * @param[in] context Pointer to the SFTP client context
510  * @param[in] handle File handle returned by SSH_FXP_OPENDIR
511  * @param[in] handleLen Length of the handle string, in bytes
512  * @return Error code
513  **/
514 
516  const uint8_t *handle, size_t handleLen)
517 {
518  error_t error;
519  size_t n;
520  size_t length;
521  uint8_t *p;
522  SftpPacketHeader *header;
523 
524  //Point to the buffer where to format the packet
525  header = (SftpPacketHeader *) context->buffer;
526 
527  //Set packet type
528  header->type = SSH_FXP_READDIR;
529  //Total length of the packet
530  length = sizeof(uint8_t);
531 
532  //Point the data payload
533  p = header->payload;
534 
535  //The request identifier is used to match each response with the
536  //corresponding request
537  context->requestId++;
538 
539  //Format request identifier
540  STORE32BE(context->requestId, p);
541 
542  //Point to the next field
543  p += sizeof(uint32_t);
544  length += sizeof(uint32_t);
545 
546  //The handle field is a handle previously returned in the response to
547  //SSH_FXP_OPENDIR
548  error = sshFormatBinaryString(handle, handleLen, p, &n);
549  //Any error to report?
550  if(error)
551  return error;
552 
553  //Total length of the packet
554  length += n;
555 
556  //Convert the length field to network byte order
557  header->length = htonl(length);
558 
559  //The packet length does not include the length field itself
560  context->requestLen = length + sizeof(uint32_t);
561  context->requestPos = 0;
562  context->responseLen = 0;
563  context->responsePos = 0;
564 
565  //Save the SFTP packet type
566  context->requestType = (SftpPacketType) header->type;
567 
568  //Debug message
569  TRACE_INFO("Sending SSH_FXP_READDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
570  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
571 
572  //Successful processing
573  return NO_ERROR;
574 }
575 
576 
577 /**
578  * @brief Format SSH_FXP_REMOVE packet
579  * @param[in] context Pointer to the SFTP client context
580  * @param[in] filename Name of the file to be removed
581  * @return Error code
582  **/
583 
585  const char_t *filename)
586 {
587  error_t error;
588  size_t n;
589  size_t length;
590  uint8_t *p;
591  SftpPacketHeader *header;
592 
593  //Point to the buffer where to format the packet
594  header = (SftpPacketHeader *) context->buffer;
595 
596  //Set packet type
597  header->type = SSH_FXP_REMOVE;
598  //Total length of the packet
599  length = sizeof(uint8_t);
600 
601  //Point the data payload
602  p = header->payload;
603 
604  //The request identifier is used to match each response with the
605  //corresponding request
606  context->requestId++;
607 
608  //Format request identifier
609  STORE32BE(context->requestId, p);
610 
611  //Point to the next field
612  p += sizeof(uint32_t);
613  length += sizeof(uint32_t);
614 
615  //The filename field specifies the file to be removed
616  error = sftpFormatPath(context, filename, p, &n);
617  //Any error to report?
618  if(error)
619  return error;
620 
621  //Total length of the packet
622  length += n;
623 
624  //Convert the length field to network byte order
625  header->length = htonl(length);
626 
627  //The packet length does not include the length field itself
628  context->requestLen = length + sizeof(uint32_t);
629  context->requestPos = 0;
630  context->responseLen = 0;
631  context->responsePos = 0;
632 
633  //Save the SFTP packet type
634  context->requestType = (SftpPacketType) header->type;
635 
636  //Debug message
637  TRACE_INFO("Sending SSH_FXP_REMOVE packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
638  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
639 
640  //Successful processing
641  return NO_ERROR;
642 }
643 
644 
645 /**
646  * @brief Format SSH_FXP_MKDIR packet
647  * @param[in] context Pointer to the SFTP client context
648  * @param[in] path Directory to be created
649  * @return Error code
650  **/
651 
653  const char_t *path)
654 {
655  error_t error;
656  size_t n;
657  size_t length;
658  uint8_t *p;
659  SftpPacketHeader *header;
661 
662  //Point to the buffer where to format the packet
663  header = (SftpPacketHeader *) context->buffer;
664 
665  //Set packet type
666  header->type = SSH_FXP_MKDIR;
667  //Total length of the packet
668  length = sizeof(uint8_t);
669 
670  //Point the data payload
671  p = header->payload;
672 
673  //The request identifier is used to match each response with the
674  //corresponding request
675  context->requestId++;
676 
677  //Format request identifier
678  STORE32BE(context->requestId, p);
679 
680  //Point to the next field
681  p += sizeof(uint32_t);
682  length += sizeof(uint32_t);
683 
684  //The path field specifies the directory to be created
685  error = sftpFormatPath(context, path, p, &n);
686  //Any error to report?
687  if(error)
688  return error;
689 
690  //Point to the next field
691  p += n;
692  length += n;
693 
694  //The 'attrs' field specifies the modifications to be made to its attributes
695  osMemset(&attributes, 0, sizeof(SftpFileAttrs));
696 
697  //Format ATTRS compound data
698  error = sftpFormatAttributes(context->version, &attributes, p, &n);
699  //Any error to report?
700  if(error)
701  return error;
702 
703  //Total length of the packet
704  length += n;
705 
706  //Convert the length field to network byte order
707  header->length = htonl(length);
708 
709  //The packet length does not include the length field itself
710  context->requestLen = length + sizeof(uint32_t);
711  context->requestPos = 0;
712  context->responseLen = 0;
713  context->responsePos = 0;
714 
715  //Save the SFTP packet type
716  context->requestType = (SftpPacketType) header->type;
717 
718  //Debug message
719  TRACE_INFO("Sending SSH_FXP_MKDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
720  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
721 
722  //Successful processing
723  return NO_ERROR;
724 }
725 
726 
727 /**
728  * @brief Format SSH_FXP_RMDIR packet
729  * @param[in] context Pointer to the SFTP client context
730  * @param[in] path Directory to be removed
731  * @return Error code
732  **/
733 
735  const char_t *path)
736 {
737  error_t error;
738  size_t n;
739  size_t length;
740  uint8_t *p;
741  SftpPacketHeader *header;
742 
743  //Point to the buffer where to format the packet
744  header = (SftpPacketHeader *) context->buffer;
745 
746  //Set packet type
747  header->type = SSH_FXP_RMDIR;
748  //Total length of the packet
749  length = sizeof(uint8_t);
750 
751  //Point the data payload
752  p = header->payload;
753 
754  //The request identifier is used to match each response with the
755  //corresponding request
756  context->requestId++;
757 
758  //Format request identifier
759  STORE32BE(context->requestId, p);
760 
761  //Point to the next field
762  p += sizeof(uint32_t);
763  length += sizeof(uint32_t);
764 
765  //The path field specifies the directory to be removed
766  error = sftpFormatPath(context, path, p, &n);
767  //Any error to report?
768  if(error)
769  return error;
770 
771  //Total length of the packet
772  length += n;
773 
774  //Convert the length field to network byte order
775  header->length = htonl(length);
776 
777  //The packet length does not include the length field itself
778  context->requestLen = length + sizeof(uint32_t);
779  context->requestPos = 0;
780  context->responseLen = 0;
781  context->responsePos = 0;
782 
783  //Save the SFTP packet type
784  context->requestType = (SftpPacketType) header->type;
785 
786  //Debug message
787  TRACE_INFO("Sending SSH_FXP_RMDIR packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
788  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
789 
790  //Successful processing
791  return NO_ERROR;
792 }
793 
794 
795 /**
796  * @brief Format SSH_FXP_REALPATH packet
797  * @param[in] context Pointer to the SFTP client context
798  * @param[in] path Path name to be canonicalized
799  * @return Error code
800  **/
801 
803  const char_t *path)
804 {
805  error_t error;
806  size_t n;
807  size_t length;
808  uint8_t *p;
809  SftpPacketHeader *header;
810 
811  //Point to the buffer where to format the packet
812  header = (SftpPacketHeader *) context->buffer;
813 
814  //Set packet type
815  header->type = SSH_FXP_REALPATH;
816  //Total length of the packet
817  length = sizeof(uint8_t);
818 
819  //Point the data payload
820  p = header->payload;
821 
822  //The request identifier is used to match each response with the
823  //corresponding request
824  context->requestId++;
825 
826  //Format request identifier
827  STORE32BE(context->requestId, p);
828 
829  //Point to the next field
830  p += sizeof(uint32_t);
831  length += sizeof(uint32_t);
832 
833  //The path field specifies the path name to be canonicalized
834  error = sshFormatString(path, p, &n);
835  //Any error to report?
836  if(error)
837  return error;
838 
839  //Total length of the packet
840  length += n;
841 
842  //Convert the length field to network byte order
843  header->length = htonl(length);
844 
845  //The packet length does not include the length field itself
846  context->requestLen = length + sizeof(uint32_t);
847  context->requestPos = 0;
848  context->responseLen = 0;
849  context->responsePos = 0;
850 
851  //Save the SFTP packet type
852  context->requestType = (SftpPacketType) header->type;
853 
854  //Debug message
855  TRACE_INFO("Sending SSH_FXP_REALPATH packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
856  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
857 
858  //Successful processing
859  return NO_ERROR;
860 }
861 
862 
863 /**
864  * @brief Format SSH_FXP_STAT packet
865  * @param[in] context Pointer to the SFTP client context
866  * @param[in] path File system object for which status is to be returned
867  * @return Error code
868  **/
869 
871  const char_t *path)
872 {
873  error_t error;
874  size_t n;
875  size_t length;
876  uint8_t *p;
877  SftpPacketHeader *header;
878 
879  //Point to the buffer where to format the packet
880  header = (SftpPacketHeader *) context->buffer;
881 
882  //Set packet type
883  header->type = SSH_FXP_STAT;
884  //Total length of the packet
885  length = sizeof(uint8_t);
886 
887  //Point the data payload
888  p = header->payload;
889 
890  //The request identifier is used to match each response with the
891  //corresponding request
892  context->requestId++;
893 
894  //Format request identifier
895  STORE32BE(context->requestId, p);
896 
897  //Point to the next field
898  p += sizeof(uint32_t);
899  length += sizeof(uint32_t);
900 
901  //The path field specifies the file system object for which status is to be
902  //returned
903  error = sftpFormatPath(context, path, p, &n);
904  //Any error to report?
905  if(error)
906  return error;
907 
908  //Total length of the packet
909  length += n;
910 
911  //Convert the length field to network byte order
912  header->length = htonl(length);
913 
914  //The packet length does not include the length field itself
915  context->requestLen = length + sizeof(uint32_t);
916  context->requestPos = 0;
917  context->responseLen = 0;
918  context->responsePos = 0;
919 
920  //Save the SFTP packet type
921  context->requestType = (SftpPacketType) header->type;
922 
923  //Debug message
924  TRACE_INFO("Sending SSH_FXP_STAT packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
925  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
926 
927  //Successful processing
928  return NO_ERROR;
929 }
930 
931 
932 /**
933  * @brief Format SSH_FXP_RENAME packet
934  * @param[in] context Pointer to the SFTP client context
935  * @param[in] oldPath Name of an existing file or directory
936  * @param[in] newPath New name for the file or directory
937  * @return Error code
938  **/
939 
941  const char_t *oldPath, const char_t *newPath)
942 {
943  error_t error;
944  size_t n;
945  size_t length;
946  uint8_t *p;
947  SftpPacketHeader *header;
948 
949  //Point to the buffer where to format the packet
950  header = (SftpPacketHeader *) context->buffer;
951 
952  //Set packet type
953  header->type = SSH_FXP_RENAME;
954  //Total length of the packet
955  length = sizeof(uint8_t);
956 
957  //Point the data payload
958  p = header->payload;
959 
960  //The request identifier is used to match each response with the
961  //corresponding request
962  context->requestId++;
963 
964  //Format request identifier
965  STORE32BE(context->requestId, p);
966 
967  //Point to the next field
968  p += sizeof(uint32_t);
969  length += sizeof(uint32_t);
970 
971  //The oldpath field is the name of an existing file or directory
972  error = sftpFormatPath(context, oldPath, p, &n);
973  //Any error to report?
974  if(error)
975  return error;
976 
977  //Point to the next field
978  p += n;
979  length += n;
980 
981  //The newpath field is the new name for the file or directory
982  error = sftpFormatPath(context, newPath, p, &n);
983  //Any error to report?
984  if(error)
985  return error;
986 
987  //Total length of the packet
988  length += n;
989 
990  //Convert the length field to network byte order
991  header->length = htonl(length);
992 
993  //The packet length does not include the length field itself
994  context->requestLen = length + sizeof(uint32_t);
995  context->requestPos = 0;
996  context->responseLen = 0;
997  context->responsePos = 0;
998 
999  //Save the SFTP packet type
1000  context->requestType = (SftpPacketType) header->type;
1001 
1002  //Debug message
1003  TRACE_INFO("Sending SSH_FXP_RENAME packet (%" PRIuSIZE " bytes)...\r\n", context->requestLen);
1004  TRACE_VERBOSE_ARRAY(" ", context->buffer, context->requestLen);
1005 
1006  //Successful processing
1007  return NO_ERROR;
1008 }
1009 
1010 
1011 /**
1012  * @brief Parse SSH_FXP_VERSION packet
1013  * @param[in] context Pointer to the SFTP client context
1014  * @param[in] packet Pointer to packet
1015  * @param[in] length Length of the packet, in bytes
1016  * @return Error code
1017  **/
1018 
1020  const uint8_t *packet, size_t length)
1021 {
1022  error_t error;
1023  uint32_t version;
1024  const uint8_t *p;
1025  SshString extensionName;
1026  SshString extensionValue;
1027 
1028  //Debug message
1029  TRACE_INFO("SSH_FXP_VERSION packet received (%" PRIuSIZE " bytes)...\r\n", length);
1030  TRACE_VERBOSE_ARRAY(" ", packet, length);
1031 
1032  //An SSH_FXP_VERSION packet is sent in response to an SSH_FXP_INIT request
1033  if(context->requestType != SSH_FXP_INIT)
1034  return ERROR_INVALID_TYPE;
1035 
1036  //Point to the first field of the packet
1037  p = packet;
1038 
1039  //Malformed packet?
1040  if(length < sizeof(uint32_t))
1041  return ERROR_INVALID_PACKET;
1042 
1043  //The SSH_FXP_VERSION packet contains the lowest of its own and the
1044  //client's version number
1045  version = LOAD32BE(p);
1046 
1047  //Point to the next field
1048  p += sizeof(uint32_t);
1049  length -= sizeof(uint32_t);
1050 
1051  //Parse extensions
1052  while(length > 0)
1053  {
1054  //Decode extension name
1055  error = sshParseString(p, length, &extensionName);
1056  //Any error to report?
1057  if(error)
1058  return error;
1059 
1060  //Point to the next field
1061  p += sizeof(uint32_t) + extensionName.length;
1062  length -= sizeof(uint32_t) + extensionName.length;
1063 
1064  //Decode extension value
1065  error = sshParseString(p, length, &extensionValue);
1066  //Any error to report?
1067  if(error)
1068  return error;
1069 
1070  //Point to the next field
1071  p += sizeof(uint32_t) + extensionValue.length;
1072  length -= sizeof(uint32_t) + extensionValue.length;
1073  }
1074 
1075  //Sanity check
1076  if(version < SFTP_CLIENT_MIN_VERSION || version > SFTP_CLIENT_MAX_VERSION)
1077  return ERROR_INVALID_VERSION;
1078 
1079  //From then on, both parties must use the same version of the protocol
1080  context->version = (SftpVersion) version;
1081 
1082  //Successful processing
1083  return NO_ERROR;
1084 }
1085 
1086 
1087 /**
1088  * @brief Parse SSH_FXP_STATUS packet
1089  * @param[in] context Pointer to the SFTP client context
1090  * @param[in] packet Pointer to packet
1091  * @param[in] length Length of the packet, in bytes
1092  * @return Error code
1093  **/
1094 
1096  const uint8_t *packet, size_t length)
1097 {
1098  error_t error;
1099  uint32_t id;
1100  const uint8_t *p;
1101  SshString errorMessage;
1102  SshString languageTag;
1103 
1104  //Debug message
1105  TRACE_INFO("SSH_FXP_STATUS packet received (%" PRIuSIZE " bytes)...\r\n", length);
1106  TRACE_VERBOSE_ARRAY(" ", packet, length);
1107 
1108  //All requests can return an SSH_FXP_STATUS response upon failure
1109  if(context->requestType == SSH_FXP_INIT)
1110  return ERROR_INVALID_TYPE;
1111 
1112  //Point to the first field of the packet
1113  p = packet;
1114 
1115  //Malformed packet?
1116  if(length < sizeof(uint32_t))
1117  return ERROR_INVALID_PACKET;
1118 
1119  //Each response packet begins with the request identifier
1120  id = LOAD32BE(p);
1121 
1122  //The request identifier is used to match each response with the
1123  //corresponding request
1124  if(id != context->requestId)
1125  return ERROR_WRONG_IDENTIFIER;
1126 
1127  //Point to the next field
1128  p += sizeof(uint32_t);
1129  length -= sizeof(uint32_t);
1130 
1131  //Malformed packet?
1132  if(length < sizeof(uint32_t))
1133  return ERROR_INVALID_PACKET;
1134 
1135  //The status code indicates the result of the requested operation
1136  context->statusCode = LOAD32BE(p);
1137 
1138  //Point to the next field
1139  p += sizeof(uint32_t);
1140  length -= sizeof(uint32_t);
1141 
1142  //In version 3, the SSH_FXP_STATUS message was changed to include fields
1143  //'error message' and 'language tag'
1144  if(context->version >= SFTP_VERSION_3)
1145  {
1146  //Decode description string
1147  error = sshParseString(p, length, &errorMessage);
1148  //Any error to report?
1149  if(error)
1150  return error;
1151 
1152  //Point to the next field
1153  p += sizeof(uint32_t) + errorMessage.length;
1154  length -= sizeof(uint32_t) + errorMessage.length;
1155 
1156  //Decode language tag
1157  error = sshParseString(p, length, &languageTag);
1158  //Any error to report?
1159  if(error)
1160  return error;
1161 
1162  //Point to the next field
1163  p += sizeof(uint32_t) + languageTag.length;
1164  length -= sizeof(uint32_t) + languageTag.length;
1165  }
1166 
1167  //Malformed message?
1168  if(length != 0)
1169  return ERROR_INVALID_MESSAGE;
1170 
1171  //Check the result of the requested operation
1172  if(context->statusCode == SSH_FX_OK)
1173  {
1174  //If no data needs to be returned to the client, the SSH_FXP_STATUS
1175  //response with SSH_FX_OK status is appropriate
1176  if(context->requestType == SSH_FXP_CLOSE ||
1177  context->requestType == SSH_FXP_WRITE ||
1178  context->requestType == SSH_FXP_SETSTAT ||
1179  context->requestType == SSH_FXP_FSETSTAT ||
1180  context->requestType == SSH_FXP_REMOVE ||
1181  context->requestType == SSH_FXP_MKDIR ||
1182  context->requestType == SSH_FXP_RMDIR ||
1183  context->requestType == SSH_FXP_RENAME ||
1184  context->requestType == SSH_FXP_SYMLINK)
1185  {
1186  //The value SSH_FX_OK indicates success
1187  error = NO_ERROR;
1188  }
1189  else
1190  {
1191  //Unexpected SSH_FXP_STATUS packet
1192  error = ERROR_INVALID_TYPE;
1193  }
1194  }
1195  else
1196  {
1197  //All other values indicate failure
1198  error = ERROR_UNEXPECTED_RESPONSE;
1199  }
1200 
1201  //Return status code
1202  return error;
1203 }
1204 
1205 
1206 /**
1207  * @brief Parse SSH_FXP_HANDLE packet
1208  * @param[in] context Pointer to the SFTP client context
1209  * @param[in] packet Pointer to packet
1210  * @param[in] length Length of the packet, in bytes
1211  * @return Error code
1212  **/
1213 
1215  const uint8_t *packet, size_t length)
1216 {
1217  error_t error;
1218  uint32_t id;
1219  const uint8_t *p;
1220  SshBinaryString handle;
1221 
1222  //Debug message
1223  TRACE_INFO("SSH_FXP_HANDLE packet received (%" PRIuSIZE " bytes)...\r\n", length);
1224  TRACE_VERBOSE_ARRAY(" ", packet, length);
1225 
1226  //The SSH_FXP_HANDLE message is used to return a file handle (for
1227  //SSH_FXP_OPEN and SSH_FXP_OPENDIR requests)
1228  if(context->requestType != SSH_FXP_OPEN &&
1229  context->requestType != SSH_FXP_OPENDIR)
1230  {
1231  return ERROR_INVALID_TYPE;
1232  }
1233 
1234  //Point to the first field of the packet
1235  p = packet;
1236 
1237  //Malformed packet?
1238  if(length < sizeof(uint32_t))
1239  return ERROR_INVALID_PACKET;
1240 
1241  //Each response packet begins with the request identifier
1242  id = LOAD32BE(p);
1243 
1244  //The request identifier is used to match each response with the
1245  //corresponding request
1246  if(id != context->requestId)
1247  return ERROR_WRONG_IDENTIFIER;
1248 
1249  //Point to the next field
1250  p += sizeof(uint32_t);
1251  length -= sizeof(uint32_t);
1252 
1253  //The handle field is an arbitrary string that identifies a file or
1254  //directory on the server
1255  error = sshParseBinaryString(p, length, &handle);
1256  //Any error to report?
1257  if(error)
1258  return error;
1259 
1260  //Point to the next field
1261  p += sizeof(uint32_t) + handle.length;
1262  length -= sizeof(uint32_t) + handle.length;
1263 
1264  //Malformed message?
1265  if(length != 0)
1266  return ERROR_INVALID_PACKET;
1267 
1268  //The length of the handle string must not exceed 256 data bytes
1269  if(handle.length > SFTP_CLIENT_MAX_HANDLE_SIZE)
1270  return ERROR_INVALID_HANDLE;
1271 
1272  //The handle is opaque to the client. The client must not attempt to
1273  //interpret or modify it in any way
1274  osMemcpy(context->handle, handle.value, handle.length);
1275 
1276  //Save the length of the handle string
1277  context->handleLen = handle.length;
1278 
1279  //Successful processing
1280  return NO_ERROR;
1281 }
1282 
1283 
1284 /**
1285  * @brief Parse SSH_FXP_DATA packet
1286  * @param[in] context Pointer to the SFTP client context
1287  * @param[in] packet Pointer to packet
1288  * @param[in] fragLen Number of bytes available on hand
1289  * @param[in] totalLen Total length of the packet, in bytes
1290  * @return Error code
1291  **/
1292 
1294  const uint8_t *packet, size_t fragLen, size_t totalLen)
1295 {
1296  error_t error;
1297  uint32_t id;
1298  const uint8_t *p;
1300 
1301  //Debug message
1302  TRACE_INFO("SSH_FXP_DATA packet received (%" PRIuSIZE " bytes)...\r\n", totalLen);
1303  TRACE_VERBOSE_ARRAY(" ", packet, fragLen);
1304 
1305  //Sanity check
1306  if(fragLen != sizeof(SftpFxpDataHeader))
1307  return ERROR_INVALID_PACKET;
1308 
1309  //SSH_FXP_DATA is used to return data from SSH_FXP_READ
1310  if(context->requestType != SSH_FXP_READ)
1311  return ERROR_INVALID_TYPE;
1312 
1313  //Point to the first field of the packet
1314  p = packet;
1315 
1316  //Malformed packet?
1317  if(totalLen < sizeof(uint32_t))
1318  return ERROR_INVALID_PACKET;
1319 
1320  //Each response packet begins with the request identifier
1321  id = LOAD32BE(p);
1322 
1323  //The request identifier is used to match each response with the
1324  //corresponding request
1325  if(id != context->requestId)
1326  return ERROR_WRONG_IDENTIFIER;
1327 
1328  //Point to the next field
1329  p += sizeof(uint32_t);
1330  totalLen -= sizeof(uint32_t);
1331 
1332  //The data field is a byte string containing the requested data
1333  error = sshParseBinaryString(p, totalLen, &data);
1334  //Any error to report?
1335  if(error)
1336  return error;
1337 
1338  //Point to the data payload
1339  p += sizeof(uint32_t);
1340  totalLen -= sizeof(uint32_t);
1341 
1342  //Malformed packet?
1343  if(data.length != totalLen)
1344  return ERROR_INVALID_PACKET;
1345 
1346  //The data string may be at most the number of bytes requested in a
1347  //SSH_FXP_READ request, but may also be shorter if end of file is reached
1348  if(data.length > context->dataLen)
1349  return ERROR_INVALID_LENGTH;
1350 
1351  //Save the actual number of data bytes in the SSH_FXP_DATA response
1352  context->dataLen = data.length;
1353 
1354  //Successful processing
1355  return NO_ERROR;
1356 }
1357 
1358 
1359 /**
1360  * @brief Parse SSH_FXP_NAME packet
1361  * @param[in] context Pointer to the SFTP client context
1362  * @param[in] packet Pointer to packet
1363  * @param[in] fragLen Number of bytes available on hand
1364  * @param[in] totalLen Total length of the packet, in bytes
1365  * @return Error code
1366  **/
1367 
1369  const uint8_t *packet, size_t fragLen, size_t totalLen)
1370 {
1371  error_t error;
1372  size_t n;
1373  uint32_t id;
1374  uint32_t count;
1375  SftpName name;
1376  const uint8_t *p;
1377 
1378  //Debug message
1379  TRACE_INFO("SSH_FXP_NAME packet received (%" PRIuSIZE " bytes)...\r\n", totalLen);
1380  TRACE_VERBOSE_ARRAY(" ", packet, fragLen);
1381 
1382  //SSH_FXP_NAME is used to return one or more file names from an SSH_FXP_READDIR
1383  //or SSH_FXP_REALPATH request
1384  if(context->requestType != SSH_FXP_READDIR &&
1385  context->requestType != SSH_FXP_REALPATH)
1386  {
1387  return ERROR_INVALID_TYPE;
1388  }
1389 
1390  //Point to the first field of the packet
1391  p = packet;
1392 
1393  //Malformed packet?
1394  if(fragLen < sizeof(uint32_t) || fragLen > totalLen)
1395  return ERROR_INVALID_PACKET;
1396 
1397  //Each response packet begins with the request identifier
1398  id = LOAD32BE(p);
1399 
1400  //The request identifier is used to match each response with the
1401  //corresponding request
1402  if(id != context->requestId)
1403  return ERROR_WRONG_IDENTIFIER;
1404 
1405  //Point to the next field
1406  p += sizeof(uint32_t);
1407  fragLen -= sizeof(uint32_t);
1408  totalLen -= sizeof(uint32_t);
1409 
1410  //Malformed packet?
1411  if(fragLen < sizeof(uint32_t))
1412  return ERROR_INVALID_PACKET;
1413 
1414  //Get the number of names returned in this response
1415  count = LOAD32BE(p);
1416 
1417  //Point to the next field
1418  p += sizeof(uint32_t);
1419  fragLen -= sizeof(uint32_t);
1420  totalLen -= sizeof(uint32_t);
1421 
1422  //SSH_FXP_READDIR or SSH_FXP_REALPATH request?
1423  if(context->requestType == SSH_FXP_READDIR)
1424  {
1425  //Each SSH_FXP_READDIR request returns one or more file names with full
1426  //file attributes for each file
1427  if(count < 1)
1428  return ERROR_INVALID_PACKET;
1429  }
1430  else
1431  {
1432  //The server will respond to an SSH_FXP_REALPATH request with an SSH_FXP_NAME
1433  //packet containing only one name and a dummy attributes value
1434  if(count != 1)
1435  return ERROR_INVALID_PACKET;
1436 
1437  //Parse file name and attributes
1438  error = sftpParseName(context->version, &name, p, fragLen, &n);
1439  //Any error to report?
1440  if(error)
1441  return error;
1442 
1443  //Malformed packet?
1444  if(fragLen != n || totalLen != n)
1445  return ERROR_INVALID_PACKET;
1446  }
1447 
1448  //Move the remaining data bytes to the start of the buffer
1449  osMemmove(context->buffer, p, fragLen);
1450 
1451  //Number of data bytes left to process
1452  context->dataLen = totalLen;
1453  context->responseLen = fragLen;
1454  context->responsePos = 0;
1455 
1456  //Successful processing
1457  return NO_ERROR;
1458 }
1459 
1460 
1461 /**
1462  * @brief Parse SSH_FXP_ATTRS packet
1463  * @param[in] context Pointer to the SFTP client context
1464  * @param[in] packet Pointer to packet
1465  * @param[in] length Length of the packet, in bytes
1466  * @return Error code
1467  **/
1468 
1470  const uint8_t *packet, size_t length)
1471 {
1472  error_t error;
1473  size_t n;
1474  uint32_t id;
1475  const uint8_t *p;
1477 
1478  //Debug message
1479  TRACE_INFO("SSH_FXP_ATTRS packet received (%" PRIuSIZE " bytes)...\r\n", length);
1480  TRACE_VERBOSE_ARRAY(" ", packet, length);
1481 
1482  //SSH_FXP_ATTRS is used to return file attributes from SSH_FXP_STAT,
1483  //SSH_FXP_LSTAT, and SSH_FXP_FSTAT requests
1484  if(context->requestType != SSH_FXP_STAT &&
1485  context->requestType != SSH_FXP_LSTAT &&
1486  context->requestType != SSH_FXP_FSTAT)
1487  {
1488  return ERROR_INVALID_TYPE;
1489  }
1490 
1491  //Point to the first field of the packet
1492  p = packet;
1493 
1494  //Malformed packet?
1495  if(length < sizeof(uint32_t))
1496  return ERROR_INVALID_PACKET;
1497 
1498  //Each response packet begins with the request identifier
1499  id = LOAD32BE(p);
1500 
1501  //The request identifier is used to match each response with the
1502  //corresponding request
1503  if(id != context->requestId)
1504  return ERROR_WRONG_IDENTIFIER;
1505 
1506  //Point to the next field
1507  p += sizeof(uint32_t);
1508  length -= sizeof(uint32_t);
1509 
1510  //Parse ATTRS compound data
1511  error = sftpParseAttributes(context->version, &attributes, p, length, &n);
1512  //Any error to report?
1513  if(error)
1514  return error;
1515 
1516  //Malformed packet?
1517  if(length != n)
1518  return ERROR_INVALID_PACKET;
1519 
1520  //Move the remaining data bytes to the start of the buffer
1521  osMemmove(context->buffer, p, length);
1522 
1523  //Number of data bytes left to process
1524  context->dataLen = length;
1525  context->responseLen = length;
1526  context->responsePos = 0;
1527 
1528  //Successful processing
1529  return NO_ERROR;
1530 }
1531 
1532 #endif
uint8_t version
Definition: coap_common.h:177
#define PRIuSIZE
char char_t
Definition: compiler_port.h:48
#define LOAD32BE(p)
Definition: cpu_endian.h:210
#define htonl(value)
Definition: cpu_endian.h:414
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
Debugging facilities.
#define TRACE_INFO(...)
Definition: debug.h:95
#define TRACE_VERBOSE_ARRAY(p, a, n)
Definition: debug.h:125
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
@ ERROR_INVALID_HANDLE
Definition: error.h:280
@ ERROR_UNEXPECTED_RESPONSE
Definition: error.h:70
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_VERSION
Definition: error.h:118
uint8_t data[]
Definition: ethernet.h:222
uint8_t p
Definition: ndp.h:300
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemmove(dest, src, length)
Definition: os_port.h:147
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
Path manipulation helper functions.
uint8_t attributes[]
Definition: radius.h:88
char_t name[]
#define SFTP_CLIENT_MAX_VERSION
Definition: sftp_client.h:54
#define SftpClientContext
Definition: sftp_client.h:103
#define SFTP_CLIENT_MAX_HANDLE_SIZE
Definition: sftp_client.h:82
error_t sftpFormatPath(SftpClientContext *context, const char_t *path, uint8_t *p, size_t *written)
Format pathname.
Helper functions for SFTP client.
error_t sftpClientParseFxpAttrs(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_ATTRS packet.
error_t sftpClientFormatFxpInit(SftpClientContext *context, uint32_t version)
Format SSH_FXP_INIT packet.
error_t sftpClientFormatFxpRealPath(SftpClientContext *context, const char_t *path)
Format SSH_FXP_REALPATH packet.
error_t sftpClientParseFxpData(SftpClientContext *context, const uint8_t *packet, size_t fragLen, size_t totalLen)
Parse SSH_FXP_DATA packet.
error_t sftpClientParseFxpHandle(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_HANDLE packet.
error_t sftpClientParseFxpVersion(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_VERSION packet.
error_t sftpClientFormatFxpOpenDir(SftpClientContext *context, const char_t *path)
Format SSH_FXP_OPENDIR packet.
error_t sftpClientParseFxpStatus(SftpClientContext *context, const uint8_t *packet, size_t length)
Parse SSH_FXP_STATUS packet.
error_t sftpClientFormatFxpRename(SftpClientContext *context, const char_t *oldPath, const char_t *newPath)
Format SSH_FXP_RENAME packet.
error_t sftpClientFormatFxpClose(SftpClientContext *context, const uint8_t *handle, size_t handleLen)
Format SSH_FXP_CLOSE packet.
error_t sftpClientFormatFxpReadDir(SftpClientContext *context, const uint8_t *handle, size_t handleLen)
Format SSH_FXP_READDIR packet.
error_t sftpClientParseFxpName(SftpClientContext *context, const uint8_t *packet, size_t fragLen, size_t totalLen)
Parse SSH_FXP_NAME packet.
error_t sftpClientFormatFxpMkDir(SftpClientContext *context, const char_t *path)
Format SSH_FXP_MKDIR packet.
error_t sftpClientFormatFxpRmDir(SftpClientContext *context, const char_t *path)
Format SSH_FXP_RMDIR packet.
error_t sftpClientFormatFxpOpen(SftpClientContext *context, const char_t *filename, uint32_t pflags)
Format SSH_FXP_OPEN packet.
error_t sftpClientFormatFxpStat(SftpClientContext *context, const char_t *path)
Format SSH_FXP_STAT packet.
error_t sftpClientFormatFxpRead(SftpClientContext *context, const uint8_t *handle, size_t handleLen, uint64_t offset, uint32_t dataLen)
Format SSH_FXP_READ packet.
error_t sftpClientFormatFxpWrite(SftpClientContext *context, const uint8_t *handle, size_t handleLen, uint64_t offset, uint32_t dataLen)
Format SSH_FXP_WRITE packet.
error_t sftpClientFormatFxpRemove(SftpClientContext *context, const char_t *filename)
Format SSH_FXP_REMOVE packet.
SFTP packet parsing and formatting.
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
error_t sftpFormatAttributes(SftpVersion version, const SftpFileAttrs *attributes, uint8_t *p, size_t *written)
Format file attributes.
Definition: sftp_common.c:255
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
@ SSH_FX_OK
Definition: sftp_common.h:171
SftpPacketType
SFTP packet types.
Definition: sftp_common.h:134
@ SSH_FXP_SETSTAT
Definition: sftp_common.h:143
@ SSH_FXP_RENAME
Definition: sftp_common.h:152
@ SSH_FXP_READ
Definition: sftp_common.h:139
@ SSH_FXP_FSETSTAT
Definition: sftp_common.h:144
@ SSH_FXP_MKDIR
Definition: sftp_common.h:148
@ SSH_FXP_SYMLINK
Definition: sftp_common.h:154
@ SSH_FXP_STAT
Definition: sftp_common.h:151
@ SSH_FXP_FSTAT
Definition: sftp_common.h:142
@ SSH_FXP_REMOVE
Definition: sftp_common.h:147
@ SSH_FXP_CLOSE
Definition: sftp_common.h:138
@ SSH_FXP_OPENDIR
Definition: sftp_common.h:145
@ SSH_FXP_LSTAT
Definition: sftp_common.h:141
@ SSH_FXP_RMDIR
Definition: sftp_common.h:149
@ SSH_FXP_REALPATH
Definition: sftp_common.h:150
@ SSH_FXP_INIT
Definition: sftp_common.h:135
@ SSH_FXP_OPEN
Definition: sftp_common.h:137
@ SSH_FXP_READDIR
Definition: sftp_common.h:146
@ SSH_FXP_WRITE
Definition: sftp_common.h:140
SftpFxpDataHeader
Definition: sftp_common.h:231
SftpPacketHeader
Definition: sftp_common.h:219
uint32_t dataLen
Definition: sftp_common.h:229
SftpVersion
SFTP protocol version.
Definition: sftp_common.h:118
@ SFTP_VERSION_3
Definition: sftp_common.h:122
Secure Shell (SSH)
error_t sshFormatString(const char_t *value, uint8_t *p, size_t *written)
Format a string.
Definition: ssh_misc.c:1384
error_t sshParseBinaryString(const uint8_t *p, size_t length, SshBinaryString *string)
Parse a binary string.
Definition: ssh_misc.c:1189
error_t sshFormatBinaryString(const void *value, size_t valueLen, uint8_t *p, size_t *written)
Format a binary string.
Definition: ssh_misc.c:1415
error_t sshParseString(const uint8_t *p, size_t length, SshString *string)
Parse a string.
Definition: ssh_misc.c:1152
SSH helper functions.
File attributes.
Definition: sftp_common.h:247
Name structure.
Definition: sftp_common.h:265
Binary string.
Definition: ssh_types.h:67
const uint8_t * value
Definition: ssh_types.h:68
size_t length
Definition: ssh_types.h:69
String.
Definition: ssh_types.h:56
size_t length
Definition: ssh_types.h:58
uint8_t length
Definition: tcp.h:368
char_t filename[]
Definition: tftp_common.h:93