ssh_connection.c
Go to the documentation of this file.
1 /**
2  * @file ssh_connection.c
3  * @brief SSH connection protocol
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 SSH_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ssh/ssh.h"
36 #include "ssh/ssh_connection.h"
37 #include "ssh/ssh_channel.h"
38 #include "ssh/ssh_packet.h"
39 #include "ssh/ssh_misc.h"
40 #include "debug.h"
41 
42 //Check SSH stack configuration
43 #if (SSH_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Send SSH_MSG_CHANNEL_OPEN message
48  * @param[in] channel Handle referencing an SSH channel
49  * @param[in] channelType NULL-terminated string containing the channel type
50  * @param[in] channelParams Pointer to the channel specific parameters
51  * @return Error code
52  **/
53 
54 error_t sshSendChannelOpen(SshChannel *channel, const char_t *channelType,
55  const void *channelParams)
56 {
57  error_t error;
58  size_t length;
59  uint8_t *message;
60  SshConnection *connection;
61 
62  //Point to the SSH connection
63  connection = channel->connection;
64 
65  //Point to the buffer where to format the message
66  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
67 
68  //Format SSH_MSG_CHANNEL_OPEN message
69  error = sshFormatChannelOpen(channel, channelType, channelParams, message,
70  &length);
71 
72  //Check status code
73  if(!error)
74  {
75  //Debug message
76  TRACE_INFO("Sending SSH_MSG_CHANNEL_OPEN message (%" PRIuSIZE " bytes)...\r\n", length);
78 
79  //Send message
80  error = sshSendPacket(connection, message, length);
81  }
82 
83  //Return status code
84  return error;
85 }
86 
87 
88 /**
89  * @brief Send SSH_MSG_CHANNEL_OPEN_CONFIRMATION message
90  * @param[in] channel Handle referencing an SSH channel
91  * @return Error code
92  **/
93 
95 {
96  error_t error;
97  size_t length;
98  uint8_t *message;
99  SshConnection *connection;
100 
101  //Point to the SSH connection
102  connection = channel->connection;
103 
104  //Point to the buffer where to format the message
105  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
106 
107  //Format SSH_MSG_CHANNEL_OPEN_CONFIRMATION message
108  error = sshFormatChannelOpenConfirmation(channel, message, &length);
109 
110  //Check status code
111  if(!error)
112  {
113  //Debug message
114  TRACE_INFO("Sending SSH_MSG_CHANNEL_OPEN_CONFIRMATION message (%" PRIuSIZE " bytes)...\r\n", length);
116 
117  //Send message
118  error = sshSendPacket(connection, message, length);
119  }
120 
121  //Check status code
122  if(!error)
123  {
124  //Update the state of the channel
125  channel->state = SSH_CHANNEL_STATE_OPEN;
126  }
127 
128  //Return status code
129  return error;
130 }
131 
132 
133 /**
134  * @brief Format SSH_MSG_CHANNEL_OPEN_FAILURE message
135  * @param[in] connection Pointer to the SSH connection
136  * @param[in] recipientChannel Channel number given in the original open request
137  * @param[in] reasonCode Reason code value
138  * @param[in] description NULL-terminating description string
139  * @return Error code
140  **/
141 
143  uint32_t recipientChannel, uint32_t reasonCode, const char_t *description)
144 {
145  error_t error;
146  size_t length;
147  uint8_t *message;
148 
149  //Point to the buffer where to format the message
150  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
151 
152  //Format SSH_MSG_CHANNEL_OPEN_FAILURE message
153  error = sshFormatChannelOpenFailure(connection, recipientChannel, reasonCode,
155 
156  //Check status code
157  if(!error)
158  {
159  //Debug message
160  TRACE_INFO("Sending SSH_MSG_CHANNEL_OPEN_FAILURE message (%" PRIuSIZE " bytes)...\r\n", length);
162 
163  //Send message
164  error = sshSendPacket(connection, message, length);
165  }
166 
167  //Return status code
168  return error;
169 }
170 
171 
172 /**
173  * @brief Send SSH_MSG_CHANNEL_WINDOW_ADJUST message
174  * @param[in] channel Handle referencing an SSH channel
175  * @param[in] windowSizeInc Number of bytes to add
176  * @return Error code
177  **/
178 
179 error_t sshSendChannelWindowAdjust(SshChannel *channel, size_t windowSizeInc)
180 {
181  error_t error;
182  size_t length;
183  uint8_t *message;
184  SshConnection *connection;
185 
186  //Point to the SSH connection
187  connection = channel->connection;
188 
189  //Point to the buffer where to format the message
190  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
191 
192  //Format SSH_MSG_CHANNEL_WINDOW_ADJUST message
193  error = sshFormatChannelWindowAdjust(channel, windowSizeInc, message, &length);
194 
195  //Check status code
196  if(!error)
197  {
198  //Debug message
199  TRACE_DEBUG("Sending SSH_MSG_CHANNEL_WINDOW_ADJUST message (%" PRIuSIZE " bytes)...\r\n", length);
201 
202  //Send message
203  error = sshSendPacket(connection, message, length);
204  }
205 
206  //Return status code
207  return error;
208 }
209 
210 
211 /**
212  * @brief Send SSH_MSG_CHANNEL_DATA message
213  * @param[in] channel Handle referencing an SSH channel
214  * @param[in] dataLen Length of the payload data, in bytes
215  * @return Error code
216  **/
217 
219 {
220  error_t error;
221  size_t length;
222  uint8_t *message;
223  SshConnection *connection;
224 
225  //Point to the SSH connection
226  connection = channel->connection;
227 
228  //Point to the buffer where to format the message
229  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
230 
231  //Format SSH_MSG_CHANNEL_DATA message
232  error = sshFormatChannelData(channel, dataLen, message, &length);
233 
234  //Check status code
235  if(!error)
236  {
237  //Debug message
238  TRACE_DEBUG("Sending SSH_MSG_CHANNEL_DATA message (%" PRIuSIZE " bytes)...\r\n", length);
240 
241  //Send message
242  error = sshSendPacket(connection, message, length);
243  }
244 
245  //Return status code
246  return error;
247 }
248 
249 
250 /**
251  * @brief Send SSH_MSG_CHANNEL_EOF message
252  * @param[in] channel Handle referencing an SSH channel
253  * @return Error code
254  **/
255 
257 {
258  error_t error;
259  size_t length;
260  uint8_t *message;
261  SshConnection *connection;
262 
263  //Point to the SSH connection
264  connection = channel->connection;
265 
266  //Point to the buffer where to format the message
267  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
268 
269  //Format SSH_MSG_CHANNEL_EOF message
270  error = sshFormatChannelEof(channel, message, &length);
271 
272  //Check status code
273  if(!error)
274  {
275  //Debug message
276  TRACE_INFO("Sending SSH_MSG_CHANNEL_EOF message (%" PRIuSIZE " bytes)...\r\n", length);
278 
279  //Send message
280  error = sshSendPacket(connection, message, length);
281  }
282 
283  //Check status code
284  if(!error)
285  {
286  //The channel remains open after this message, and more data may still
287  //be sent in the other direction (refer to RFC 4254, section 5.3)
288  channel->eofSent = TRUE;
289  }
290 
291  //Return status code
292  return error;
293 }
294 
295 
296 /**
297  * @brief Send SSH_MSG_CHANNEL_CLOSE message
298  * @param[in] channel Handle referencing an SSH channel
299  * @return Error code
300  **/
301 
303 {
304  error_t error;
305  size_t length;
306  uint8_t *message;
307  SshConnection *connection;
308 
309  //Point to the SSH connection
310  connection = channel->connection;
311 
312  //Point to the buffer where to format the message
313  message = connection->buffer + SSH_PACKET_HEADER_SIZE;
314 
315  //Format SSH_MSG_CHANNEL_CLOSE message
316  error = sshFormatChannelClose(channel, message, &length);
317 
318  //Check status code
319  if(!error)
320  {
321  //Debug message
322  TRACE_INFO("Sending SSH_MSG_CHANNEL_CLOSE message (%" PRIuSIZE " bytes)...\r\n", length);
324 
325  //Send message
326  error = sshSendPacket(connection, message, length);
327  }
328 
329  //Check status code
330  if(!error)
331  {
332  //An SSH_MSG_CHANNEL_CLOSE message has been successfully sent
333  channel->closeSent = TRUE;
334 
335  //Check whether an SSH_MSG_CHANNEL_CLOSE message has been received
336  if(channel->closeReceived)
337  {
338  //The channel is considered closed for a party when it has both sent
339  //and received SSH_MSG_CHANNEL_CLOSE (refer to RFC 4254, section 5.3)
340  channel->state = SSH_CHANNEL_STATE_CLOSED;
341  }
342  }
343 
344  //Return status code
345  return error;
346 }
347 
348 
349 /**
350  * @brief Format SSH_MSG_CHANNEL_OPEN message
351  * @param[in] channel Handle referencing an SSH channel
352  * @param[in] channelType NULL-terminated string containing the channel type
353  * @param[in] channelParams Pointer to the channel specific parameters
354  * @param[out] p Buffer where to format the message
355  * @param[out] length Length of the resulting message, in bytes
356  * @return Error code
357  **/
358 
359 error_t sshFormatChannelOpen(SshChannel *channel, const char_t *channelType,
360  const void *channelParams, uint8_t *p, size_t *length)
361 {
362  error_t error;
363  size_t n;
364 
365  //Total length of the message
366  *length = 0;
367 
368  //Set message type
369  p[0] = SSH_MSG_CHANNEL_OPEN;
370 
371  //Point to the first field of the message
372  p += sizeof(uint8_t);
373  *length += sizeof(uint8_t);
374 
375  //Set channel type
376  error = sshFormatString(channelType, p, &n);
377  //Any error to report?
378  if(error)
379  return error;
380 
381  //Point to the next field
382  p += n;
383  *length += n;
384 
385  //Set channel number
386  STORE32BE(channel->localChannelNum, p);
387 
388  //Point to the next field
389  p += sizeof(uint32_t);
390  *length += sizeof(uint32_t);
391 
392  //Set initial window size
394 
395  //Point to the next field
396  p += sizeof(uint32_t);
397  *length += sizeof(uint32_t);
398 
399  //Set maximum packet size
401 
402  //Point to the next field
403  p += sizeof(uint32_t);
404  *length += sizeof(uint32_t);
405 
406  //Check channel type
407  if(!osStrcmp(channelType, "session"))
408  {
409  //A "session" channel does not specify any type-specific data
410  n = 0;
411  }
412  else if(!osStrcmp(channelType, "forwarded-tcpip"))
413  {
414  //Format "forwarded-tcpip" channel specific data
415  error = sshFormatForwardedTcpIpParams(channelParams, p, &n);
416  }
417  else if(!osStrcmp(channelType, "direct-tcpip"))
418  {
419  //Format "direct-tcpip" channel specific data
420  error = sshFormatDirectTcpIpParams(channelParams, p, &n);
421  }
422  else
423  {
424  //Report an error
425  error = ERROR_UNSUPPORTED_TYPE;
426  }
427 
428  //Check status code
429  if(!error)
430  {
431  //Total length of the message
432  *length += n;
433  }
434 
435  //Return status code
436  return error;
437 }
438 
439 
440 /**
441  * @brief Format "forwarded-tcpip" channel parameters
442  * @param[in] params Pointer to the channel specific parameters
443  * @param[out] p Output stream where to write the channel specific data
444  * @param[out] written Total number of bytes that have been written
445  * @return Error code
446  **/
447 
449  uint8_t *p, size_t *written)
450 {
451  error_t error;
452  size_t n;
453 
454  //Check parameters
455  if(params == NULL)
457 
458  //Total length of the channel specific data
459  *written = 0;
460 
461  //Set 'address that was connected' field
462  error = sshFormatBinaryString(params->addrConnected.value,
463  params->addrConnected.length, p, &n);
464  //Any error to report?
465  if(error)
466  return error;
467 
468  //Point to the next field
469  p += n;
470  *written += n;
471 
472  //Set 'port that was connected' field
473  STORE32BE(params->portConnected, p);
474 
475  //Point to the next field
476  p += sizeof(uint32_t);
477  *written += sizeof(uint32_t);
478 
479  //Set 'originator IP address' field
480  error = sshFormatBinaryString(params->originIpAddr.value,
481  params->originIpAddr.length, p, &n);
482  //Any error to report?
483  if(error)
484  return error;
485 
486  //Point to the next field
487  p += n;
488  *written += n;
489 
490  //Set 'originator port' field
491  STORE32BE(params->originPort, p);
492 
493  //Total number of bytes that have been written
494  *written += sizeof(uint32_t);
495 
496  //Successful processing
497  return NO_ERROR;
498 }
499 
500 
501 /**
502  * @brief Format "direct-tcpip" channel parameters
503  * @param[in] params Pointer to the channel specific parameters
504  * @param[out] p Output stream where to write the channel specific data
505  * @param[out] written Total number of bytes that have been written
506  * @return Error code
507  **/
508 
510  uint8_t *p, size_t *written)
511 {
512  error_t error;
513  size_t n;
514 
515  //Check parameters
516  if(params == NULL)
518 
519  //Total length of the channel specific data
520  *written = 0;
521 
522  //The 'host to connect' field specifies the TCP/IP host where the recipient
523  //should connect the channel
524  error = sshFormatBinaryString(params->hostToConnect.value,
525  params->hostToConnect.length, p, &n);
526  //Any error to report?
527  if(error)
528  return error;
529 
530  //Point to the next field
531  p += n;
532  *written += n;
533 
534  //The 'port to connect' field specifies the port where the recipient should
535  //connect the channel
536  STORE32BE(params->portToConnect, p);
537 
538  //Point to the next field
539  p += sizeof(uint32_t);
540  *written += sizeof(uint32_t);
541 
542  //The 'originator IP address' field is the numeric IP address of the machine
543  //from where the connection request originates
544  error = sshFormatBinaryString(params->originIpAddr.value,
545  params->originIpAddr.length, p, &n);
546  //Any error to report?
547  if(error)
548  return error;
549 
550  //Point to the next field
551  p += n;
552  *written += n;
553 
554  //The 'originator port' field is the port on the host from where the
555  //connection originated
556  STORE32BE(params->originPort, p);
557 
558  //Total number of bytes that have been written
559  *written += sizeof(uint32_t);
560 
561  //Successful processing
562  return NO_ERROR;
563 }
564 
565 
566 /**
567  * @brief Format SSH_MSG_CHANNEL_OPEN_CONFIRMATION message
568  * @param[in] channel Handle referencing an SSH channel
569  * @param[out] p Buffer where to format the message
570  * @param[out] length Length of the resulting message, in bytes
571  * @return Error code
572  **/
573 
575  size_t *length)
576 {
577  //Total length of the message
578  *length = 0;
579 
580  //Set message type
582 
583  //Point to the first field of the message
584  p += sizeof(uint8_t);
585  *length += sizeof(uint8_t);
586 
587  //Set recipient channel
588  STORE32BE(channel->remoteChannelNum, p);
589 
590  //Point to the next field
591  p += sizeof(uint32_t);
592  *length += sizeof(uint32_t);
593 
594  //Set sender channel
595  STORE32BE(channel->localChannelNum, p);
596 
597  //Point to the next field
598  p += sizeof(uint32_t);
599  *length += sizeof(uint32_t);
600 
601  //Set initial window size
603 
604  //Point to the next field
605  p += sizeof(uint32_t);
606  *length += sizeof(uint32_t);
607 
608  //Set maximum packet size
610 
611  //Total length of the message
612  *length += sizeof(uint32_t);
613 
614  //Successful processing
615  return NO_ERROR;
616 }
617 
618 
619 /**
620  * @brief Format SSH_MSG_CHANNEL_OPEN_FAILURE message
621  * @param[in] connection Pointer to the SSH connection
622  * @param[in] recipientChannel Channel number given in the original open request
623  * @param[in] reasonCode Reason code value
624  * @param[in] description NULL-terminating description string
625  * @param[out] p Buffer where to format the message
626  * @param[out] length Length of the resulting message, in bytes
627  * @return Error code
628  **/
629 
631  uint32_t recipientChannel, uint32_t reasonCode, const char_t *description,
632  uint8_t *p, size_t *length)
633 {
634  error_t error;
635  size_t n;
636 
637  //Total length of the message
638  *length = 0;
639 
640  //Set message type
642 
643  //Point to the first field of the message
644  p += sizeof(uint8_t);
645  *length += sizeof(uint8_t);
646 
647  //Set recipient channel
648  STORE32BE(recipientChannel, p);
649 
650  //Point to the next field
651  p += sizeof(uint32_t);
652  *length += sizeof(uint32_t);
653 
654  //Set reason code
655  STORE32BE(reasonCode, p);
656 
657  //Point to the next field
658  p += sizeof(uint32_t);
659  *length += sizeof(uint32_t);
660 
661  //Set description string
662  error = sshFormatString(description, p, &n);
663  //Any error to report?
664  if(error)
665  return error;
666 
667  //Point to the next field
668  p += n;
669  *length += n;
670 
671  //Set language tag
672  error = sshFormatString("en", p, &n);
673  //Any error to report?
674  if(error)
675  return error;
676 
677  //Total length of the message
678  *length += n;
679 
680  //Successful processing
681  return NO_ERROR;
682 }
683 
684 
685 /**
686  * @brief Format SSH_MSG_CHANNEL_WINDOW_ADJUST message
687  * @param[in] channel Handle referencing an SSH channel
688  * @param[in] windowSizeInc Number of bytes to add
689  * @param[out] p Buffer where to format the message
690  * @param[out] length Length of the resulting message, in bytes
691  * @return Error code
692  **/
693 
694 error_t sshFormatChannelWindowAdjust(SshChannel *channel, size_t windowSizeInc,
695  uint8_t *p, size_t *length)
696 {
697  //Total length of the message
698  *length = 0;
699 
700  //Set message type
702 
703  //Point to the first field of the message
704  p += sizeof(uint8_t);
705  *length += sizeof(uint8_t);
706 
707  //Set recipient channel
708  STORE32BE(channel->remoteChannelNum, p);
709 
710  //Point to the next field
711  p += sizeof(uint32_t);
712  *length += sizeof(uint32_t);
713 
714  //Set the number of bytes to add
715  STORE32BE(windowSizeInc, p);
716 
717  //Total length of the message
718  *length += sizeof(uint32_t);
719 
720  //Successful processing
721  return NO_ERROR;
722 }
723 
724 
725 /**
726  * @brief Format SSH_MSG_CHANNEL_DATA message
727  * @param[in] channel Handle referencing an SSH channel
728  * @param[in] dataLen Length of the payload data, in bytes
729  * @param[out] p Buffer where to format the message
730  * @param[out] length Length of the resulting message, in bytes
731  * @return Error code
732  **/
733 
735  uint8_t *p, size_t *length)
736 {
738 
739  //Point to the transmission buffer
740  txBuffer = &channel->txBuffer;
741 
742  //Check the length of the payload data
744  return ERROR_INVALID_LENGTH;
745 
746  //Total length of the message
747  *length = 0;
748 
749  //Set message type
750  p[0] = SSH_MSG_CHANNEL_DATA;
751 
752  //Point to the first field of the message
753  p += sizeof(uint8_t);
754  *length += sizeof(uint8_t);
755 
756  //Set recipient channel
757  STORE32BE(channel->remoteChannelNum, p);
758 
759  //Point to the next field
760  p += sizeof(uint32_t);
761  *length += sizeof(uint32_t);
762 
763  //The data is preceded by a uint32 containing its length
764  STORE32BE(dataLen, p);
765 
766  //Point to the payload data
767  p += sizeof(uint32_t);
768  *length += sizeof(uint32_t);
769 
770  //Check whether the specified data crosses channel buffer boundaries
771  if((txBuffer->readPos + dataLen) <= SSH_CHANNEL_BUFFER_SIZE)
772  {
773  //Copy the payload data
774  osMemcpy(p, txBuffer->data + txBuffer->readPos, dataLen);
775  }
776  else
777  {
778  //Copy the first part of the payload data
779  osMemcpy(p, txBuffer->data + txBuffer->readPos,
780  SSH_CHANNEL_BUFFER_SIZE - txBuffer->readPos);
781 
782  //Wrap around to the beginning of the circular buffer
784  txBuffer->data, txBuffer->readPos + dataLen -
786  }
787 
788  //Total length of the message
789  *length += dataLen;
790 
791  //Successful processing
792  return NO_ERROR;
793 }
794 
795 
796 /**
797  * @brief Format SSH_MSG_CHANNEL_EOF message
798  * @param[in] channel Handle referencing an SSH channel
799  * @param[out] p Buffer where to format the message
800  * @param[out] length Length of the resulting message, in bytes
801  * @return Error code
802  **/
803 
804 error_t sshFormatChannelEof(SshChannel *channel, uint8_t *p, size_t *length)
805 {
806  //Total length of the message
807  *length = 0;
808 
809  //Set message type
810  p[0] = SSH_MSG_CHANNEL_EOF;
811 
812  //Point to the first field of the message
813  p += sizeof(uint8_t);
814  *length += sizeof(uint8_t);
815 
816  //Set recipient channel
817  STORE32BE(channel->remoteChannelNum, p);
818 
819  //Total length of the message
820  *length += sizeof(uint32_t);
821 
822  //Successful processing
823  return NO_ERROR;
824 }
825 
826 
827 /**
828  * @brief Format SSH_MSG_CHANNEL_CLOSE message
829  * @param[in] channel Handle referencing an SSH channel
830  * @param[out] p Buffer where to format the message
831  * @param[out] length Length of the resulting message, in bytes
832  * @return Error code
833  **/
834 
835 error_t sshFormatChannelClose(SshChannel *channel, uint8_t *p, size_t *length)
836 {
837  //Total length of the message
838  *length = 0;
839 
840  //Set message type
842 
843  //Point to the first field of the message
844  p += sizeof(uint8_t);
845  *length += sizeof(uint8_t);
846 
847  //Set recipient channel
848  STORE32BE(channel->remoteChannelNum, p);
849 
850  //Total length of the message
851  *length += sizeof(uint32_t);
852 
853  //Successful processing
854  return NO_ERROR;
855 }
856 
857 
858 /**
859  * @brief Parse SSH_MSG_CHANNEL_OPEN message
860  * @param[in] connection Pointer to the SSH connection
861  * @param[in] message Pointer to message
862  * @param[in] length Length of the message, in bytes
863  * @return Error code
864  **/
865 
867  const uint8_t *message, size_t length)
868 {
869  error_t error;
870  uint_t i;
871  const uint8_t *p;
872  uint32_t senderChannel;
873  uint32_t initialWindowSize;
874  uint32_t maxPacketSize;
875  SshString channelType;
876  SshChannel *channel;
877  SshContext *context;
878 
879  //Point to the SSH context
880  context = connection->context;
881 
882  //Debug message
883  TRACE_INFO("SSH_MSG_CHANNEL_OPEN message received (%" PRIuSIZE " bytes)...\r\n", length);
885 
886  //Check connection state
887  if(connection->state != SSH_CONN_STATE_OPEN)
889 
890  //Sanity check
891  if(length < sizeof(uint8_t))
892  return ERROR_INVALID_MESSAGE;
893 
894  //Point to the first field of the message
895  p = message + sizeof(uint8_t);
896  //Remaining bytes to process
897  length -= sizeof(uint8_t);
898 
899  //Decode the channel type
900  error = sshParseString(p, length, &channelType);
901  //Any error to report?
902  if(error)
903  return error;
904 
905  //Point to the next field
906  p += sizeof(uint32_t) + channelType.length;
907  length -= sizeof(uint32_t) + channelType.length;
908 
909  //Malformed message?
910  if(length < sizeof(uint32_t))
911  return ERROR_INVALID_MESSAGE;
912 
913  //Get sender channel number
914  senderChannel = LOAD32BE(p);
915 
916  //Point to the next field
917  p += sizeof(uint32_t);
918  length -= sizeof(uint32_t);
919 
920  //Malformed message?
921  if(length < sizeof(uint32_t))
922  return ERROR_INVALID_MESSAGE;
923 
924  //Get initial window size
925  initialWindowSize = LOAD32BE(p);
926 
927  //Point to the next field
928  p += sizeof(uint32_t);
929  length -= sizeof(uint32_t);
930 
931  //Malformed message?
932  if(length < sizeof(uint32_t))
933  return ERROR_INVALID_MESSAGE;
934 
935  //Get maximum packet size
936  maxPacketSize = LOAD32BE(p);
937 
938  //Point to the next field
939  p += sizeof(uint32_t);
940  length -= sizeof(uint32_t);
941 
942  //Debug message
943  TRACE_DEBUG(" Sender Channel = %" PRIu32 "\r\n", senderChannel);
944  TRACE_DEBUG(" Initial Window Size = %" PRIu32 "\r\n", initialWindowSize);
945  TRACE_DEBUG(" Max Packet Size = %" PRIu32 "\r\n", maxPacketSize);
946 
947  //Sanity check
948  if(maxPacketSize == 0)
950 
951  //Each side must associate a unique number to the channel
952  if(!sshCheckRemoteChannelNum(connection, senderChannel))
954 
955  //Check channel type
956  if(sshCompareString(&channelType, "session"))
957  {
958  //A "session" channel does not specify any type-specific data
959  if(length != 0)
960  return ERROR_INVALID_MESSAGE;
961 
962  //Check whether SSH operates as a client or a server
963  if(connection->context->mode == SSH_OPERATION_MODE_CLIENT)
964  {
965  //Client implementations should reject any session channel open
966  //requests to make it more difficult for a corrupt server to attack
967  //the client (refer to RFC 4254, section 6.1)
968  error = sshSendChannelOpenFailure(connection, senderChannel,
969  SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "Administratively prohibited");
970  }
971  else
972  {
973  //The server decides whether it can open the channel
974  channel = sshCreateChannel(connection);
975 
976  //Valid channel handle?
977  if(channel != NULL)
978  {
979  //Save the channel number allocated by the other side
980  channel->remoteChannelNum = senderChannel;
981 
982  //Save channel's parameters
983  channel->txWindowSize = initialWindowSize;
984  channel->maxPacketSize = maxPacketSize;
985 
986  //Send an SSH_MSG_CHANNEL_OPEN_CONFIRMATION message to the client
987  error = sshSendChannelOpenConfirmation(channel);
988  }
989  else
990  {
991  //Send an SSH_MSG_CHANNEL_OPEN_FAILURE message to the client
992  error = sshSendChannelOpenFailure(connection, senderChannel,
993  SSH_OPEN_RESOURCE_SHORTAGE, "Maximum number of channels exceeded");
994  }
995  }
996  }
997  else
998  {
999  //Initialize status code
1000  error = ERROR_UNKNOWN_TYPE;
1001 
1002  //Multiple callbacks may be registered
1003  for(i = 0; i < SSH_MAX_CHANNEL_OPEN_CALLBACKS &&
1004  error == ERROR_UNKNOWN_TYPE; i++)
1005  {
1006  //Valid callback function?
1007  if(context->channelOpenCallback[i] != NULL)
1008  {
1009  //Process channel open request
1010  error = context->channelOpenCallback[i](connection, &channelType,
1011  senderChannel, initialWindowSize, maxPacketSize, p, length,
1012  context->channelOpenParam[i]);
1013  }
1014  }
1015 
1016  //Check status code
1017  if(error == ERROR_UNKNOWN_TYPE)
1018  {
1019  //Send an SSH_MSG_CHANNEL_OPEN_FAILURE message to the peer
1020  error = sshSendChannelOpenFailure(connection, senderChannel,
1021  SSH_OPEN_UNKNOWN_CHANNEL_TYPE, "Unknown channel type");
1022  }
1023  }
1024 
1025  //Return status code
1026  return error;
1027 }
1028 
1029 
1030 /**
1031  * @brief Parse "forwarded-tcpip" channel parameters
1032  * @param[in] p Pointer to the channel specific data
1033  * @param[in] length Length of the channel specific data, in bytes
1034  * @param[out] params Information resulting from the parsing process
1035  * @return Error code
1036  **/
1037 
1039  SshForwardedTcpIpParams *params)
1040 {
1041  error_t error;
1042 
1043  //Parse 'address that was connected' field
1044  error = sshParseString(p, length, &params->addrConnected);
1045  //Any error to report?
1046  if(error)
1047  return error;
1048 
1049  //Point to the next field
1050  p += sizeof(uint32_t) + params->addrConnected.length;
1051  length -= sizeof(uint32_t) + params->addrConnected.length;
1052 
1053  //Malformed message?
1054  if(length < sizeof(uint32_t))
1055  return ERROR_INVALID_MESSAGE;
1056 
1057  //Parse 'port that was connected' field
1058  params->portConnected = LOAD32BE(p);
1059 
1060  //Invalid port number?
1061  if(params->portConnected > SSH_MAX_PORT_NUM)
1062  return ERROR_INVALID_PORT;
1063 
1064  //Point to the next field
1065  p += sizeof(uint32_t);
1066  length -= sizeof(uint32_t);
1067 
1068  //Parse 'originator IP address' field
1069  error = sshParseString(p, length, &params->originIpAddr);
1070  //Any error to report?
1071  if(error)
1072  return error;
1073 
1074  //Point to the next field
1075  p += sizeof(uint32_t) + params->originIpAddr.length;
1076  length -= sizeof(uint32_t) + params->originIpAddr.length;
1077 
1078  //Malformed message?
1079  if(length != sizeof(uint32_t))
1080  return ERROR_INVALID_MESSAGE;
1081 
1082  //Parse 'originator port' field
1083  params->originPort = LOAD32BE(p);
1084 
1085  //Invalid port number?
1086  if(params->originPort > SSH_MAX_PORT_NUM)
1087  return ERROR_INVALID_PORT;
1088 
1089  //Successful processing
1090  return NO_ERROR;
1091 }
1092 
1093 
1094 /**
1095  * @brief Parse "direct-tcpip" channel parameters
1096  * @param[in] p Pointer to the channel specific data
1097  * @param[in] length Length of the channel specific data, in bytes
1098  * @param[out] params Information resulting from the parsing process
1099  * @return Error code
1100  **/
1101 
1103  SshDirectTcpIpParams *params)
1104 {
1105  error_t error;
1106 
1107  //The 'host to connect' field specifies the TCP/IP host where the recipient
1108  //should connect the channel
1109  error = sshParseString(p, length, &params->hostToConnect);
1110  //Any error to report?
1111  if(error)
1112  return error;
1113 
1114  //Point to the next field
1115  p += sizeof(uint32_t) + params->hostToConnect.length;
1116  length -= sizeof(uint32_t) + params->hostToConnect.length;
1117 
1118  //Malformed message?
1119  if(length < sizeof(uint32_t))
1120  return ERROR_INVALID_MESSAGE;
1121 
1122  //The 'port to connect' field specifies the port where the recipient should
1123  //connect the channel
1124  params->portToConnect = LOAD32BE(p);
1125 
1126  //Invalid port number?
1127  if(params->portToConnect > SSH_MAX_PORT_NUM)
1128  return ERROR_INVALID_PORT;
1129 
1130  //Point to the next field
1131  p += sizeof(uint32_t);
1132  length -= sizeof(uint32_t);
1133 
1134  //The 'originator IP address' field is the numeric IP address of the machine
1135  //from where the connection request originates
1136  error = sshParseString(p, length, &params->originIpAddr);
1137  //Any error to report?
1138  if(error)
1139  return error;
1140 
1141  //Point to the next field
1142  p += sizeof(uint32_t) + params->originIpAddr.length;
1143  length -= sizeof(uint32_t) + params->originIpAddr.length;
1144 
1145  //Malformed message?
1146  if(length != sizeof(uint32_t))
1147  return ERROR_INVALID_MESSAGE;
1148 
1149  //The 'originator port' field is the port on the host from where the
1150  //connection originated
1151  params->originPort = LOAD32BE(p);
1152 
1153  //Invalid port number?
1154  if(params->originPort > SSH_MAX_PORT_NUM)
1155  return ERROR_INVALID_PORT;
1156 
1157  //Successful processing
1158  return NO_ERROR;
1159 }
1160 
1161 
1162 /**
1163  * @brief Parse SSH_MSG_CHANNEL_OPEN_CONFIRMATION message
1164  * @param[in] connection Pointer to the SSH connection
1165  * @param[in] message Pointer to message
1166  * @param[in] length Length of the message, in bytes
1167  * @return Error code
1168  **/
1169 
1171  const uint8_t *message, size_t length)
1172 {
1173  error_t error;
1174  const uint8_t *p;
1175  uint32_t recipientChannel;
1176  uint32_t senderChannel;
1177  uint32_t initialWindowSize;
1178  uint32_t maxPacketSize;
1179  SshChannel *channel;
1180 
1181  //Debug message
1182  TRACE_INFO("SSH_MSG_CHANNEL_OPEN_CONFIRMATION message received (%" PRIuSIZE " bytes)...\r\n", length);
1184 
1185  //Check connection state
1186  if(connection->state != SSH_CONN_STATE_OPEN)
1187  return ERROR_UNEXPECTED_MESSAGE;
1188 
1189  //Sanity check
1190  if(length < sizeof(uint8_t))
1191  return ERROR_INVALID_MESSAGE;
1192 
1193  //Point to the first field of the message
1194  p = message + sizeof(uint8_t);
1195  //Remaining bytes to process
1196  length -= sizeof(uint8_t);
1197 
1198  //Malformed message?
1199  if(length < sizeof(uint32_t))
1200  return ERROR_INVALID_MESSAGE;
1201 
1202  //Decode the recipient channel
1203  recipientChannel = LOAD32BE(p);
1204 
1205  //Point to the next field
1206  p += sizeof(uint32_t);
1207  length -= sizeof(uint32_t);
1208 
1209  //Malformed message?
1210  if(length < sizeof(uint32_t))
1211  return ERROR_INVALID_MESSAGE;
1212 
1213  //Decode the sender channel
1214  senderChannel = LOAD32BE(p);
1215 
1216  //Point to the next field
1217  p += sizeof(uint32_t);
1218  length -= sizeof(uint32_t);
1219 
1220  //Malformed message?
1221  if(length < sizeof(uint32_t))
1222  return ERROR_INVALID_MESSAGE;
1223 
1224  //Decode initial window size
1225  initialWindowSize = LOAD32BE(p);
1226 
1227  //Point to the next field
1228  p += sizeof(uint32_t);
1229  length -= sizeof(uint32_t);
1230 
1231  //Malformed message?
1232  if(length != sizeof(uint32_t))
1233  return ERROR_INVALID_MESSAGE;
1234 
1235  //Decode maximum packet size
1236  maxPacketSize = LOAD32BE(p);
1237 
1238  //Debug message
1239  TRACE_DEBUG(" Recipient Channel = %" PRIu32 "\r\n", recipientChannel);
1240  TRACE_DEBUG(" Sender Channel = %" PRIu32 "\r\n", senderChannel);
1241  TRACE_DEBUG(" Initial Window Size = %" PRIu32 "\r\n", initialWindowSize);
1242  TRACE_DEBUG(" Max Packet Size = %" PRIu32 "\r\n", maxPacketSize);
1243 
1244  //Sanity check
1245  if(maxPacketSize == 0)
1246  return ERROR_ILLEGAL_PARAMETER;
1247 
1248  //Acquire exclusive access to the SSH context
1249  osAcquireMutex(&connection->context->mutex);
1250 
1251  //Each side must associate a unique number to the channel
1252  if(sshCheckRemoteChannelNum(connection, senderChannel))
1253  {
1254  //Point to the matching channel
1255  channel = sshGetChannel(connection, recipientChannel);
1256 
1257  //Valid channel?
1258  if(channel != NULL)
1259  {
1260  //Check channel state
1261  if(channel->state == SSH_CHANNEL_STATE_RESERVED)
1262  {
1263  //Save the channel number allocated by the other side
1264  channel->remoteChannelNum = senderChannel;
1265 
1266  //Save channel's parameters
1267  channel->txWindowSize = initialWindowSize;
1268  channel->maxPacketSize = maxPacketSize;
1269 
1270  //Update the state of the channel
1271  channel->state = SSH_CHANNEL_STATE_OPEN;
1272  //Update channel related events
1273  sshUpdateChannelEvents(channel);
1274 
1275  //Successfull processing
1276  error = NO_ERROR;
1277  }
1278  else
1279  {
1280  //Invalid channel state
1281  error = ERROR_UNEXPECTED_MESSAGE;
1282  }
1283  }
1284  else
1285  {
1286  //The recipient channel number is not valid
1287  error = ERROR_INVALID_CHANNEL;
1288  }
1289  }
1290  else
1291  {
1292  //The sender channel number is not valid
1293  error = ERROR_ILLEGAL_PARAMETER;
1294  }
1295 
1296  //Release exclusive access to the SSH context
1297  osReleaseMutex(&connection->context->mutex);
1298 
1299  //Return status code
1300  return error;
1301 }
1302 
1303 
1304 /**
1305  * @brief Parse SSH_MSG_CHANNEL_OPEN_FAILURE message
1306  * @param[in] connection Pointer to the SSH connection
1307  * @param[in] message Pointer to message
1308  * @param[in] length Length of the message, in bytes
1309  * @return Error code
1310  **/
1311 
1313  const uint8_t *message, size_t length)
1314 {
1315  error_t error;
1316  const uint8_t *p;
1317  uint32_t recipientChannel;
1318  uint32_t reasonCode;
1320  SshString languageTag;
1321  SshChannel *channel;
1322 
1323  //Debug message
1324  TRACE_INFO("SSH_MSG_CHANNEL_OPEN_FAILURE message received (%" PRIuSIZE " bytes)...\r\n", length);
1326 
1327  //Check connection state
1328  if(connection->state != SSH_CONN_STATE_OPEN)
1329  return ERROR_UNEXPECTED_MESSAGE;
1330 
1331  //Sanity check
1332  if(length < sizeof(uint8_t))
1333  return ERROR_INVALID_MESSAGE;
1334 
1335  //Point to the first field of the message
1336  p = message + sizeof(uint8_t);
1337  //Remaining bytes to process
1338  length -= sizeof(uint8_t);
1339 
1340  //Malformed message?
1341  if(length < sizeof(uint32_t))
1342  return ERROR_INVALID_MESSAGE;
1343 
1344  //Decode the recipient channel
1345  recipientChannel = LOAD32BE(p);
1346 
1347  //Point to the next field
1348  p += sizeof(uint32_t);
1349  length -= sizeof(uint32_t);
1350 
1351  //Malformed message?
1352  if(length < sizeof(uint32_t))
1353  return ERROR_INVALID_MESSAGE;
1354 
1355  //Decode the reason code
1356  reasonCode = LOAD32BE(p);
1357  //The value of this field is not used
1358  (void) reasonCode;
1359 
1360  //Point to the next field
1361  p += sizeof(uint32_t);
1362  length -= sizeof(uint32_t);
1363 
1364  //Decode description string
1365  error = sshParseString(p, length, &description);
1366  //Any error to report?
1367  if(error)
1368  return error;
1369 
1370  //Point to the next field
1371  p += sizeof(uint32_t) + description.length;
1372  length -= sizeof(uint32_t) + description.length;
1373 
1374  //Decode language tag
1375  error = sshParseString(p, length, &languageTag);
1376  //Any error to report?
1377  if(error)
1378  return error;
1379 
1380  //Point to the next field
1381  p += sizeof(uint32_t) + languageTag.length;
1382  length -= sizeof(uint32_t) + languageTag.length;
1383 
1384  //Malformed message?
1385  if(length != 0)
1386  return ERROR_INVALID_MESSAGE;
1387 
1388  //Acquire exclusive access to the SSH context
1389  osAcquireMutex(&connection->context->mutex);
1390 
1391  //Point to the matching channel
1392  channel = sshGetChannel(connection, recipientChannel);
1393 
1394  //Valid channel?
1395  if(channel != NULL)
1396  {
1397  //Check channel state
1398  if(channel->state == SSH_CHANNEL_STATE_RESERVED)
1399  {
1400  //Update the state of the channel
1401  channel->state = SSH_CHANNEL_STATE_CLOSED;
1402  //Update channel related events
1403  sshUpdateChannelEvents(channel);
1404 
1405  //Successfull processing
1406  error = NO_ERROR;
1407  }
1408  else
1409  {
1410  //Invalid channel state
1411  error = ERROR_UNEXPECTED_MESSAGE;
1412  }
1413  }
1414  else
1415  {
1416  //The recipient channel number is not valid
1417  error = ERROR_INVALID_CHANNEL;
1418  }
1419 
1420  //Release exclusive access to the SSH context
1421  osReleaseMutex(&connection->context->mutex);
1422 
1423  //Return status code
1424  return error;
1425 }
1426 
1427 
1428 /**
1429  * @brief Parse SSH_MSG_CHANNEL_WINDOW_ADJUST message
1430  * @param[in] connection Pointer to the SSH connection
1431  * @param[in] message Pointer to message
1432  * @param[in] length Length of the message, in bytes
1433  * @return Error code
1434  **/
1435 
1437  const uint8_t *message, size_t length)
1438 {
1439  error_t error;
1440  const uint8_t *p;
1441  uint32_t recipientChannel;
1442  uint32_t windowSizeInc;
1443  SshChannel *channel;
1444  SshContext *context;
1445 
1446  //Point to the SSH context
1447  context = connection->context;
1448 
1449  //Debug message
1450  TRACE_DEBUG("SSH_MSG_CHANNEL_WINDOW_ADJUST message received (%" PRIuSIZE " bytes)...\r\n", length);
1452 
1453  //Check connection state
1454  if(connection->state != SSH_CONN_STATE_OPEN)
1455  return ERROR_UNEXPECTED_MESSAGE;
1456 
1457  //Sanity check
1458  if(length < sizeof(uint8_t))
1459  return ERROR_INVALID_MESSAGE;
1460 
1461  //Point to the first field of the message
1462  p = message + sizeof(uint8_t);
1463  //Remaining bytes to process
1464  length -= sizeof(uint8_t);
1465 
1466  //Malformed message?
1467  if(length < sizeof(uint32_t))
1468  return ERROR_INVALID_MESSAGE;
1469 
1470  //Get recipient channel number
1471  recipientChannel = LOAD32BE(p);
1472 
1473  //Point to the next field
1474  p += sizeof(uint32_t);
1475  length -= sizeof(uint32_t);
1476 
1477  //Malformed message?
1478  if(length != sizeof(uint32_t))
1479  return ERROR_INVALID_MESSAGE;
1480 
1481  //Get the number of bytes to add
1482  windowSizeInc = LOAD32BE(p);
1483 
1484  //Acquire exclusive access to the SSH context
1485  osAcquireMutex(&connection->context->mutex);
1486 
1487  //Point to the matching channel
1488  channel = sshGetChannel(connection, recipientChannel);
1489 
1490  //Valid channel?
1491  if(channel != NULL)
1492  {
1493  //Check channel state
1494  if(channel->state == SSH_CHANNEL_STATE_OPEN && !channel->closeReceived)
1495  {
1496  //Check whether the window size increment is valid
1497  if((channel->txWindowSize + windowSizeInc) >= channel->txWindowSize)
1498  {
1499  //After receiving this message, the recipient may send the given
1500  //number of bytes more than it was previously allowed to send. The
1501  //window size is incremented (refer to RFC 4254, section 5.2)
1502  channel->txWindowSize += windowSizeInc;
1503 
1504  //Check whether another SSH_MSG_CHANNEL_DATA message can be sent
1505  sshNotifyEvent(context);
1506 
1507  //Successfull processing
1508  error = NO_ERROR;
1509  }
1510  else
1511  {
1512  //The window must not be increased above 2^32 - 1 bytes
1513  error = ERROR_FLOW_CONTROL;
1514  }
1515  }
1516  else
1517  {
1518  //Invalid channel state
1519  error = ERROR_UNEXPECTED_MESSAGE;
1520  }
1521  }
1522  else
1523  {
1524  //The recipient channel number is not valid
1525  error = ERROR_INVALID_CHANNEL;
1526  }
1527 
1528  //Release exclusive access to the SSH context
1529  osReleaseMutex(&connection->context->mutex);
1530 
1531  //Return status code
1532  return error;
1533 }
1534 
1535 
1536 /**
1537  * @brief Parse SSH_MSG_CHANNEL_DATA message
1538  * @param[in] connection Pointer to the SSH connection
1539  * @param[in] message Pointer to message
1540  * @param[in] length Length of the message, in bytes
1541  * @return Error code
1542  **/
1543 
1545  const uint8_t *message, size_t length)
1546 {
1547  error_t error;
1548  const uint8_t *p;
1549  uint32_t recipientChannel;
1551  SshChannel *channel;
1552 
1553  //Debug message
1554  TRACE_DEBUG("SSH_MSG_CHANNEL_DATA message received (%" PRIuSIZE " bytes)...\r\n", length);
1556 
1557  //Check connection state
1558  if(connection->state != SSH_CONN_STATE_OPEN)
1559  return ERROR_UNEXPECTED_MESSAGE;
1560 
1561  //Sanity check
1562  if(length < sizeof(uint8_t))
1563  return ERROR_INVALID_MESSAGE;
1564 
1565  //Point to the first field of the message
1566  p = message + sizeof(uint8_t);
1567  //Remaining bytes to process
1568  length -= sizeof(uint8_t);
1569 
1570  //Malformed message?
1571  if(length < sizeof(uint32_t))
1572  return ERROR_INVALID_MESSAGE;
1573 
1574  //Get recipient channel number
1575  recipientChannel = LOAD32BE(p);
1576 
1577  //Point to the next field
1578  p += sizeof(uint32_t);
1579  length -= sizeof(uint32_t);
1580 
1581  //Decode the data field
1582  error = sshParseBinaryString(p, length, &data);
1583  //Any error to report?
1584  if(error)
1585  return error;
1586 
1587  //Point to the next field
1588  p += sizeof(uint32_t) + data.length;
1589  length -= sizeof(uint32_t) + data.length;
1590 
1591  //Malformed message?
1592  if(length != 0)
1593  return ERROR_INVALID_MESSAGE;
1594 
1595  //Acquire exclusive access to the SSH context
1596  osAcquireMutex(&connection->context->mutex);
1597 
1598  //Point to the matching channel
1599  channel = sshGetChannel(connection, recipientChannel);
1600 
1601  //Valid channel?
1602  if(channel != NULL)
1603  {
1604  //Check channel state
1605  if(channel->state == SSH_CHANNEL_STATE_OPEN && !channel->eofReceived &&
1606  !channel->closeReceived)
1607  {
1608  //Process payload data
1609  error = sshProcessChannelData(channel, data.value, data.length);
1610  }
1611  else
1612  {
1613  //Invalid channel state
1614  error = ERROR_UNEXPECTED_MESSAGE;
1615  }
1616  }
1617  else
1618  {
1619  //The recipient channel number is not valid
1620  error = ERROR_INVALID_CHANNEL;
1621  }
1622 
1623  //Release exclusive access to the SSH context
1624  osReleaseMutex(&connection->context->mutex);
1625 
1626  //Return status code
1627  return error;
1628 }
1629 
1630 
1631 /**
1632  * @brief Parse SSH_MSG_CHANNEL_EXTENDED_DATA message
1633  * @param[in] connection Pointer to the SSH connection
1634  * @param[in] message Pointer to message
1635  * @param[in] length Length of the message, in bytes
1636  * @return Error code
1637  **/
1638 
1640  const uint8_t *message, size_t length)
1641 {
1642  error_t error;
1643  const uint8_t *p;
1644  uint32_t recipientChannel;
1645  uint32_t dataType;
1647  SshChannel *channel;
1648 
1649  //Debug message
1650  TRACE_DEBUG("SSH_MSG_CHANNEL_DATA message received (%" PRIuSIZE " bytes)...\r\n", length);
1652 
1653  //Check connection state
1654  if(connection->state != SSH_CONN_STATE_OPEN)
1655  return ERROR_UNEXPECTED_MESSAGE;
1656 
1657  //Sanity check
1658  if(length < sizeof(uint8_t))
1659  return ERROR_INVALID_MESSAGE;
1660 
1661  //Point to the first field of the message
1662  p = message + sizeof(uint8_t);
1663  //Remaining bytes to process
1664  length -= sizeof(uint8_t);
1665 
1666  //Malformed message?
1667  if(length < sizeof(uint32_t))
1668  return ERROR_INVALID_MESSAGE;
1669 
1670  //Get recipient channel number
1671  recipientChannel = LOAD32BE(p);
1672 
1673  //Point to the next field
1674  p += sizeof(uint32_t);
1675  length -= sizeof(uint32_t);
1676 
1677  //Malformed message?
1678  if(length < sizeof(uint32_t))
1679  return ERROR_INVALID_MESSAGE;
1680 
1681  //Get data type code
1682  dataType = LOAD32BE(p);
1683 
1684  //Point to the next field
1685  p += sizeof(uint32_t);
1686  length -= sizeof(uint32_t);
1687 
1688  //Decode the data field
1689  error = sshParseBinaryString(p, length, &data);
1690  //Any error to report?
1691  if(error)
1692  return error;
1693 
1694  //Point to the next field
1695  p += sizeof(uint32_t) + data.length;
1696  length -= sizeof(uint32_t) + data.length;
1697 
1698  //Malformed message?
1699  if(length != 0)
1700  return ERROR_INVALID_MESSAGE;
1701 
1702  //Acquire exclusive access to the SSH context
1703  osAcquireMutex(&connection->context->mutex);
1704 
1705  //Point to the matching channel
1706  channel = sshGetChannel(connection, recipientChannel);
1707 
1708  //Valid channel?
1709  if(channel != NULL)
1710  {
1711  //Check channel state
1712  if(channel->state == SSH_CHANNEL_STATE_OPEN && !channel->eofReceived &&
1713  !channel->closeReceived)
1714  {
1715  //Process extended data
1716  error = sshProcessChannelExtendedData(channel, dataType, data.value,
1717  data.length);
1718  }
1719  else
1720  {
1721  //Invalid channel state
1722  error = ERROR_UNEXPECTED_MESSAGE;
1723  }
1724  }
1725  else
1726  {
1727  //The recipient channel number is not valid
1728  error = ERROR_INVALID_CHANNEL;
1729  }
1730 
1731  //Release exclusive access to the SSH context
1732  osReleaseMutex(&connection->context->mutex);
1733 
1734  //Return status code
1735  return error;
1736 }
1737 
1738 
1739 /**
1740  * @brief Parse SSH_MSG_CHANNEL_EOF message
1741  * @param[in] connection Pointer to the SSH connection
1742  * @param[in] message Pointer to message
1743  * @param[in] length Length of the message, in bytes
1744  * @return Error code
1745  **/
1746 
1748  const uint8_t *message, size_t length)
1749 {
1750  error_t error;
1751  const uint8_t *p;
1752  uint32_t recipientChannel;
1753  SshChannel *channel;
1754 
1755  //Debug message
1756  TRACE_INFO("SSH_MSG_CHANNEL_EOF message received (%" PRIuSIZE " bytes)...\r\n", length);
1758 
1759  //Check connection state
1760  if(connection->state != SSH_CONN_STATE_OPEN)
1761  return ERROR_UNEXPECTED_MESSAGE;
1762 
1763  //Sanity check
1764  if(length < sizeof(uint8_t))
1765  return ERROR_INVALID_MESSAGE;
1766 
1767  //Point to the first field of the message
1768  p = message + sizeof(uint8_t);
1769  //Remaining bytes to process
1770  length -= sizeof(uint8_t);
1771 
1772  //Malformed message?
1773  if(length != sizeof(uint32_t))
1774  return ERROR_INVALID_MESSAGE;
1775 
1776  //Get recipient channel number
1777  recipientChannel = LOAD32BE(p);
1778 
1779  //Acquire exclusive access to the SSH context
1780  osAcquireMutex(&connection->context->mutex);
1781 
1782  //Point to the matching channel
1783  channel = sshGetChannel(connection, recipientChannel);
1784 
1785  //Valid channel?
1786  if(channel != NULL)
1787  {
1788  //Check channel state
1789  if(channel->state == SSH_CHANNEL_STATE_OPEN && !channel->eofReceived &&
1790  !channel->closeReceived)
1791  {
1792  //The channel remains open after this message, and more data may still
1793  //be sent in the other direction (refer to RFC 4254, section 5.3)
1794  channel->eofReceived = TRUE;
1795 
1796  //Update channel related events
1797  sshUpdateChannelEvents(channel);
1798 
1799  //Successfull processing
1800  error = NO_ERROR;
1801  }
1802  else
1803  {
1804  //Invalid channel state
1805  error = ERROR_UNEXPECTED_MESSAGE;
1806  }
1807  }
1808  else
1809  {
1810  //The recipient channel number is not valid
1811  error = ERROR_INVALID_CHANNEL;
1812  }
1813 
1814  //Release exclusive access to the SSH context
1815  osReleaseMutex(&connection->context->mutex);
1816 
1817  //Return status code
1818  return error;
1819 }
1820 
1821 
1822 /**
1823  * @brief Parse SSH_MSG_CHANNEL_CLOSE message
1824  * @param[in] connection Pointer to the SSH connection
1825  * @param[in] message Pointer to message
1826  * @param[in] length Length of the message, in bytes
1827  * @return Error code
1828  **/
1829 
1831  const uint8_t *message, size_t length)
1832 {
1833  error_t error;
1834  const uint8_t *p;
1835  uint32_t recipientChannel;
1836  SshChannel *channel;
1837 
1838  //Debug message
1839  TRACE_INFO("SSH_MSG_CHANNEL_CLOSE message received (%" PRIuSIZE " bytes)...\r\n", length);
1841 
1842  //Check connection state
1843  if(connection->state != SSH_CONN_STATE_OPEN)
1844  return ERROR_UNEXPECTED_MESSAGE;
1845 
1846  //Sanity check
1847  if(length < sizeof(uint8_t))
1848  return ERROR_INVALID_MESSAGE;
1849 
1850  //Point to the first field of the message
1851  p = message + sizeof(uint8_t);
1852  //Remaining bytes to process
1853  length -= sizeof(uint8_t);
1854 
1855  //Malformed message?
1856  if(length != sizeof(uint32_t))
1857  return ERROR_INVALID_MESSAGE;
1858 
1859  //Get recipient channel number
1860  recipientChannel = LOAD32BE(p);
1861 
1862  //Acquire exclusive access to the SSH context
1863  osAcquireMutex(&connection->context->mutex);
1864 
1865  //Point to the matching channel
1866  channel = sshGetChannel(connection, recipientChannel);
1867 
1868  //Valid channel?
1869  if(channel != NULL)
1870  {
1871  //Check channel state
1872  if(channel->state == SSH_CHANNEL_STATE_OPEN && !channel->closeReceived)
1873  {
1874  //An SSH_MSG_CHANNEL_CLOSE message has been successfully received
1875  channel->closeReceived = TRUE;
1876 
1877  //Upon receiving an SSH_MSG_CHANNEL_CLOSE message, a party must send
1878  //back an SSH_MSG_CHANNEL_CLOSE unless it has already sent this message
1879  //for the channel (refer to RFC 4254, section 5.3)
1880  if(!channel->closeSent)
1881  {
1882  //Send an SSH_MSG_CHANNEL_CLOSE message
1883  error = sshSendChannelClose(channel);
1884  }
1885  else
1886  {
1887  //The channel is considered closed for a party when it has both sent
1888  //and received SSH_MSG_CHANNEL_CLOSE
1889  channel->state = SSH_CHANNEL_STATE_CLOSED;
1890 
1891  //Successful processing
1892  error = NO_ERROR;
1893  }
1894 
1895  //Update channel related events
1896  sshUpdateChannelEvents(channel);
1897  }
1898  else
1899  {
1900  //Report an error
1901  error = ERROR_UNEXPECTED_MESSAGE;
1902  }
1903 
1904  //Check channel state
1905  if(connection->context->mode == SSH_OPERATION_MODE_SERVER &&
1906  channel->state == SSH_CHANNEL_STATE_CLOSED)
1907  {
1908  //Release SSH channel
1909  if(channel->closeRequest || !channel->channelSuccessSent)
1910  {
1911  channel->state = SSH_CHANNEL_STATE_UNUSED;
1912  }
1913  }
1914  }
1915  else
1916  {
1917  //The recipient channel number is not valid
1918  error = ERROR_INVALID_CHANNEL;
1919  }
1920 
1921  //Release exclusive access to the SSH context
1922  osReleaseMutex(&connection->context->mutex);
1923 
1924  //Return status code
1925  return error;
1926 }
1927 
1928 #endif
#define txBuffer
uint8_t message[]
Definition: chap.h:154
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
char char_t
Definition: compiler_port.h:48
#define LOAD32BE(p)
Definition: cpu_endian.h:210
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#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_ILLEGAL_PARAMETER
Definition: error.h:242
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_UNSUPPORTED_TYPE
Definition: error.h:125
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
@ ERROR_FLOW_CONTROL
Definition: error.h:277
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_CHANNEL
Definition: error.h:273
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ERROR_UNKNOWN_TYPE
Definition: error.h:294
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:194
uint8_t data[]
Definition: ethernet.h:222
uint8_t p
Definition: ndp.h:300
#define osStrcmp(s1, s2)
Definition: os_port.h:171
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define TRUE
Definition: os_port.h:50
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
uint32_t dataLen
Definition: sftp_common.h:229
SshChannel * sshCreateChannel(SshConnection *connection)
Create a new SSH channel.
Definition: ssh.c:1964
Secure Shell (SSH)
#define SSH_CHANNEL_BUFFER_SIZE
Definition: ssh.h:241
#define SSH_MAX_CHANNEL_OPEN_CALLBACKS
Definition: ssh.h:206
@ SSH_CHANNEL_STATE_RESERVED
Definition: ssh.h:1083
@ SSH_CHANNEL_STATE_OPEN
Definition: ssh.h:1084
@ SSH_CHANNEL_STATE_UNUSED
Definition: ssh.h:1082
@ SSH_CHANNEL_STATE_CLOSED
Definition: ssh.h:1085
@ SSH_CONN_STATE_OPEN
Definition: ssh.h:1071
#define SshChannel
Definition: ssh.h:887
@ SSH_OPERATION_MODE_SERVER
Definition: ssh.h:902
@ SSH_OPERATION_MODE_CLIENT
Definition: ssh.h:901
@ SSH_OPEN_ADMINISTRATIVELY_PROHIBITED
Definition: ssh.h:1029
@ SSH_OPEN_UNKNOWN_CHANNEL_TYPE
Definition: ssh.h:1031
@ SSH_OPEN_RESOURCE_SHORTAGE
Definition: ssh.h:1032
#define SshConnection
Definition: ssh.h:883
#define SSH_MAX_PACKET_SIZE
Definition: ssh.h:234
#define SshContext
Definition: ssh.h:879
@ SSH_MSG_CHANNEL_CLOSE
Definition: ssh.h:990
@ SSH_MSG_CHANNEL_WINDOW_ADJUST
Definition: ssh.h:986
@ SSH_MSG_CHANNEL_OPEN_CONFIRMATION
Definition: ssh.h:984
@ SSH_MSG_CHANNEL_DATA
Definition: ssh.h:987
@ SSH_MSG_CHANNEL_OPEN_FAILURE
Definition: ssh.h:985
@ SSH_MSG_CHANNEL_OPEN
Definition: ssh.h:983
@ SSH_MSG_CHANNEL_EOF
Definition: ssh.h:989
bool_t sshCheckRemoteChannelNum(SshConnection *connection, uint32_t remoteChannelNum)
Check remote channel number.
Definition: ssh_channel.c:141
void sshUpdateChannelEvents(SshChannel *channel)
Update SSH channel related events.
Definition: ssh_channel.c:386
SshChannel * sshGetChannel(SshConnection *connection, uint32_t localChannelNum)
Get the channel that matches the specified channel number.
Definition: ssh_channel.c:53
error_t sshProcessChannelExtendedData(SshChannel *channel, uint32_t type, const uint8_t *data, size_t length)
Process incoming extended data.
Definition: ssh_channel.c:541
error_t sshProcessChannelData(SshChannel *channel, const uint8_t *data, size_t length)
Process incoming data.
Definition: ssh_channel.c:466
SSH channel management.
error_t sshParseForwardedTcpIpParams(const uint8_t *p, size_t length, SshForwardedTcpIpParams *params)
Parse "forwarded-tcpip" channel parameters.
error_t sshParseChannelClose(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_CLOSE message.
error_t sshFormatChannelOpen(SshChannel *channel, const char_t *channelType, const void *channelParams, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_OPEN message.
error_t sshParseChannelEof(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_EOF message.
error_t sshSendChannelClose(SshChannel *channel)
Send SSH_MSG_CHANNEL_CLOSE message.
error_t sshFormatChannelData(SshChannel *channel, size_t dataLen, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_DATA message.
error_t sshParseChannelData(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_DATA message.
error_t sshSendChannelOpenConfirmation(SshChannel *channel)
Send SSH_MSG_CHANNEL_OPEN_CONFIRMATION message.
error_t sshParseChannelOpenFailure(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_OPEN_FAILURE message.
error_t sshFormatForwardedTcpIpParams(const SshForwardedTcpIpParams *params, uint8_t *p, size_t *written)
Format "forwarded-tcpip" channel parameters.
error_t sshParseChannelWindowAdjust(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_WINDOW_ADJUST message.
error_t sshSendChannelOpenFailure(SshConnection *connection, uint32_t recipientChannel, uint32_t reasonCode, const char_t *description)
Format SSH_MSG_CHANNEL_OPEN_FAILURE message.
error_t sshFormatChannelEof(SshChannel *channel, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_EOF message.
error_t sshParseChannelOpenConfirmation(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_OPEN_CONFIRMATION message.
error_t sshSendChannelEof(SshChannel *channel)
Send SSH_MSG_CHANNEL_EOF message.
error_t sshParseChannelExtendedData(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_EXTENDED_DATA message.
error_t sshFormatChannelWindowAdjust(SshChannel *channel, size_t windowSizeInc, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_WINDOW_ADJUST message.
error_t sshParseDirectTcpIpParams(const uint8_t *p, size_t length, SshDirectTcpIpParams *params)
Parse "direct-tcpip" channel parameters.
error_t sshFormatChannelClose(SshChannel *channel, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_CLOSE message.
error_t sshFormatDirectTcpIpParams(const SshDirectTcpIpParams *params, uint8_t *p, size_t *written)
Format "direct-tcpip" channel parameters.
error_t sshSendChannelData(SshChannel *channel, size_t dataLen)
Send SSH_MSG_CHANNEL_DATA message.
error_t sshParseChannelOpen(SshConnection *connection, const uint8_t *message, size_t length)
Parse SSH_MSG_CHANNEL_OPEN message.
error_t sshSendChannelOpen(SshChannel *channel, const char_t *channelType, const void *channelParams)
Send SSH_MSG_CHANNEL_OPEN message.
error_t sshFormatChannelOpenFailure(SshConnection *connection, uint32_t recipientChannel, uint32_t reasonCode, const char_t *description, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_OPEN_FAILURE message.
error_t sshFormatChannelOpenConfirmation(SshChannel *channel, uint8_t *p, size_t *length)
Format SSH_MSG_CHANNEL_OPEN_CONFIRMATION message.
error_t sshSendChannelWindowAdjust(SshChannel *channel, size_t windowSizeInc)
Send SSH_MSG_CHANNEL_WINDOW_ADJUST message.
SSH connection protocol.
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
bool_t sshCompareString(const SshString *string, const char_t *value)
Compare a binary string against the supplied value.
Definition: ssh_misc.c:1586
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
void sshNotifyEvent(SshContext *context)
Notify the SSH context that event is occurring.
Definition: ssh_misc.c:709
SSH helper functions.
#define SSH_MAX_PORT_NUM
Definition: ssh_misc.h:39
error_t sshSendPacket(SshConnection *connection, uint8_t *payload, size_t payloadLen)
Send SSH packet.
Definition: ssh_packet.c:57
SSH packet encryption/decryption.
#define SSH_PACKET_HEADER_SIZE
Definition: ssh_packet.h:38
#define SSH_CHANNEL_DATA_MSG_HEADER_SIZE
Definition: ssh_packet.h:44
#define SSH_DEFAULT_MAX_PACKET_SIZE
Definition: ssh_packet.h:42
Binary string.
Definition: ssh_types.h:67
SSH channel buffer.
Definition: ssh.h:1352
"direct-tcpip" channel specific parameters
"forwarded-tcpip" channel specific parameters
String.
Definition: ssh_types.h:56
const char_t * value
Definition: ssh_types.h:57
size_t length
Definition: ssh_types.h:58
uint8_t length
Definition: tcp.h:368
uint8_t description
Definition: tls.h:1855