ssh_server.c
Go to the documentation of this file.
1 /**
2  * @file ssh_server.c
3  * @brief SSH server
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSH Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.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_misc.h"
37 #include "ssh/ssh_server.h"
38 #include "ssh/ssh_server_misc.h"
39 #include "debug.h"
40 
41 //Check SSH stack configuration
42 #if (SSH_SUPPORT == ENABLED && SSH_SERVER_SUPPORT == ENABLED)
43 
44 
45 /**
46  * @brief Initialize settings with default values
47  * @param[out] settings Structure that contains SSH server settings
48  **/
49 
51 {
52  //Default task parameters
53  settings->task = OS_TASK_DEFAULT_PARAMS;
55  settings->task.priority = SSH_SERVER_PRIORITY;
56 
57  //TCP/IP stack context
58  settings->netContext = NULL;
59  //The SSH server is not bound to any interface
60  settings->interface = NULL;
61 
62  //SSH port number
63  settings->port = SSH_PORT;
64  //Idle connection timeout
65  settings->timeout = SSH_SERVER_TIMEOUT;
66 
67  //SSH connections
68  settings->numConnections = 0;
69  settings->connections = NULL;
70 
71  //SSH channels
72  settings->numChannels = 0;
73  settings->channels = NULL;
74 
75  //Pseudo-random number generator
76  settings->prngAlgo = NULL;
77  settings->prngContext = NULL;
78 
79 #if (SSH_PUBLIC_KEY_AUTH_SUPPORT == ENABLED)
80  //Public key authentication callback function
81  settings->publicKeyAuthCallback = NULL;
82 #endif
83 
84 #if (SSH_PUBLIC_KEY_AUTH_SUPPORT == ENABLED && SSH_CERT_SUPPORT == ENABLED)
85  //Certificate authentication callback function
86  settings->certAuthCallback = NULL;
87  //CA public key verification callback function
88  settings->caPublicKeyVerifyCallback = NULL;
89 #endif
90 
91 #if (SSH_PASSWORD_AUTH_SUPPORT == ENABLED)
92  //Password authentication callback function
93  settings->passwordAuthCallback = NULL;
94  //Password change callback function
95  settings->passwordChangeCallback = NULL;
96 #endif
97 
98 #if (SSH_SIGN_CALLBACK_SUPPORT == ENABLED)
99  //Signature generation callback function
100  settings->signGenCallback = NULL;
101  //Signature verification callback function
102  settings->signVerifyCallback = NULL;
103 #endif
104 
105 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
106  //ECDH key pair generation callback
107  settings->ecdhKeyPairGenCallback = NULL;
108  //ECDH shared secret calculation callback
109  settings->ecdhSharedSecretCalcCallback = NULL;
110 #endif
111 
112 #if (SSH_KEY_LOG_SUPPORT == ENABLED)
113  //Key logging callback (for debugging purpose only)
114  settings->keyLogCallback = NULL;
115 #endif
116 }
117 
118 
119 /**
120  * @brief Initialize SSH server context
121  * @param[in] context Pointer to the SSH server context
122  * @param[in] settings SSH server specific settings
123  * @return Error code
124  **/
125 
127  const SshServerSettings *settings)
128 {
129  error_t error;
130 
131  //Debug message
132  TRACE_INFO("Initializing SSH server...\r\n");
133 
134  //Ensure the parameters are valid
135  if(context == NULL || settings == NULL)
137 
138  //Invalid number of SSH connections?
139  if(settings->numConnections < 1 ||
141  {
143  }
144 
145  //Invalid number of SSH channels?
146  if(settings->numChannels < settings->numConnections)
148 
149  //Clear SSH server context
150  osMemset(context, 0, sizeof(SshServerContext));
151 
152  //Initialize SSH context
153  error = sshInit(&context->sshContext, settings->connections,
154  settings->numConnections, settings->channels, settings->numChannels);
155  //Any error to report?
156  if(error)
157  return error;
158 
159  //Initialize task parameters
160  context->taskParams = settings->task;
161  context->taskId = OS_INVALID_TASK_ID;
162 
163  //Attach TCP/IP stack context
164  if(settings->netContext != NULL)
165  {
166  context->netContext = settings->netContext;
167  }
168  else if(settings->interface != NULL)
169  {
170  context->netContext = settings->interface->netContext;
171  }
172  else
173  {
174  context->netContext = netGetDefaultContext();
175  }
176 
177  //Save settings
178  context->interface = settings->interface;
179  context->port = settings->port;
180  context->timeout = settings->timeout;
181 
182  //Start of exception handling block
183  do
184  {
185  //Select server operation mode
186  error = sshSetOperationMode(&context->sshContext,
188  //Any error to report?
189  if(error)
190  break;
191 
192  //Set the pseudo-random number generator to be used
193  error = sshSetPrng(&context->sshContext, settings->prngAlgo,
194  settings->prngContext);
195  //Any error to report?
196  if(error)
197  break;
198 
199 #if (SSH_PUBLIC_KEY_AUTH_SUPPORT == ENABLED)
200  //Valid public key authentication callback function?
201  if(settings->publicKeyAuthCallback != NULL)
202  {
203  //Register callback function
205  settings->publicKeyAuthCallback);
206  //Any error to report?
207  if(error)
208  break;
209  }
210 #endif
211 
212 #if (SSH_PUBLIC_KEY_AUTH_SUPPORT == ENABLED && SSH_CERT_SUPPORT == ENABLED)
213  //Valid certificate authentication callback function?
214  if(settings->certAuthCallback != NULL)
215  {
216  //Register callback function
217  error = sshRegisterCertAuthCallback(&context->sshContext,
218  settings->certAuthCallback);
219  //Any error to report?
220  if(error)
221  break;
222  }
223 
224  //Valid CA public key verification callback function?
225  if(settings->caPublicKeyVerifyCallback != NULL)
226  {
227  //Register callback function
229  settings->caPublicKeyVerifyCallback);
230  //Any error to report?
231  if(error)
232  break;
233  }
234 #endif
235 
236 #if (SSH_PASSWORD_AUTH_SUPPORT == ENABLED)
237  //Valid password authentication callback function?
238  if(settings->passwordAuthCallback != NULL)
239  {
240  //Register callback function
242  settings->passwordAuthCallback);
243  //Any error to report?
244  if(error)
245  break;
246  }
247 
248  //Valid password change callback function?
249  if(settings->passwordChangeCallback != NULL)
250  {
251  //Register callback function
253  settings->passwordChangeCallback);
254  //Any error to report?
255  if(error)
256  break;
257  }
258 #endif
259 
260 #if (SSH_SIGN_CALLBACK_SUPPORT == ENABLED)
261  //Valid signature generation callback function?
262  if(settings->signGenCallback != NULL)
263  {
264  //Register callback function
265  error = sshRegisterSignGenCallback(&context->sshContext,
266  settings->signGenCallback);
267  //Any error to report?
268  if(error)
269  break;
270  }
271 
272  //Valid signature verification callback function?
273  if(settings->signVerifyCallback != NULL)
274  {
275  //Register callback function
276  error = sshRegisterSignVerifyCallback(&context->sshContext,
277  settings->signVerifyCallback);
278  //Any error to report?
279  if(error)
280  break;
281  }
282 #endif
283 
284 #if (SSH_ECDH_CALLBACK_SUPPORT == ENABLED)
285  //Valid ECDH key pair generation callback function?
286  if(settings->ecdhKeyPairGenCallback != NULL)
287  {
288  //Register callback function
290  settings->ecdhKeyPairGenCallback);
291  //Any error to report?
292  if(error)
293  break;
294  }
295 
296  //Valid ECDH shared secret calculation callback function?
297  if(settings->ecdhSharedSecretCalcCallback != NULL)
298  {
299  //Register callback function
301  settings->ecdhSharedSecretCalcCallback);
302  //Any error to report?
303  if(error)
304  break;
305  }
306 #endif
307 
308 #if (SSH_KEY_LOG_SUPPORT == ENABLED)
309  //Valid key logging callback function?
310  if(settings->keyLogCallback != NULL)
311  {
312  //Register callback function
313  error = sshRegisterKeyLogCallback(&context->sshContext,
314  settings->keyLogCallback);
315  //Any error to report?
316  if(error)
317  break;
318  }
319 #endif
320 
321  //End of exception handling block
322  } while(0);
323 
324  //Check status code
325  if(error)
326  {
327  //Clean up side effects
328  sshServerDeinit(context);
329  }
330 
331  //Return status code
332  return error;
333 }
334 
335 
336 /**
337  * @brief Register global request callback function
338  * @param[in] context Pointer to the SSH server context
339  * @param[in] callback Global request callback function
340  * @param[in] param An opaque pointer passed to the callback function
341  * @return Error code
342  **/
343 
345  SshGlobalReqCallback callback, void *param)
346 {
347  //Register global request callback function
348  return sshRegisterGlobalRequestCallback(&context->sshContext, callback,
349  param);
350 }
351 
352 
353 /**
354  * @brief Unregister global request callback function
355  * @param[in] context Pointer to the SSH server context
356  * @param[in] callback Previously registered callback function
357  * @return Error code
358  **/
359 
361  SshGlobalReqCallback callback)
362 {
363  //Unregister global request callback function
364  return sshUnregisterGlobalRequestCallback(&context->sshContext, callback);
365 }
366 
367 
368 /**
369  * @brief Register channel request callback function
370  * @param[in] context Pointer to the SSH server context
371  * @param[in] callback Channel request callback function
372  * @param[in] param An opaque pointer passed to the callback function
373  * @return Error code
374  **/
375 
377  SshChannelReqCallback callback, void *param)
378 {
379  //Register channel request callback function
380  return sshRegisterChannelRequestCallback(&context->sshContext, callback,
381  param);
382 }
383 
384 
385 /**
386  * @brief Unregister channel request callback function
387  * @param[in] context Pointer to the SSH server context
388  * @param[in] callback Previously registered callback function
389  * @return Error code
390  **/
391 
393  SshChannelReqCallback callback)
394 {
395  //Unregister channel request callback function
396  return sshUnregisterChannelRequestCallback(&context->sshContext, callback);
397 }
398 
399 
400 /**
401  * @brief Register channel open callback function
402  * @param[in] context Pointer to the SSH server context
403  * @param[in] callback Channel open callback function
404  * @param[in] param An opaque pointer passed to the callback function
405  * @return Error code
406  **/
407 
409  SshChannelOpenCallback callback, void *param)
410 {
411  //Register channel open callback function
412  return sshRegisterChannelOpenCallback(&context->sshContext, callback,
413  param);
414 }
415 
416 
417 /**
418  * @brief Unregister channel open callback function
419  * @param[in] context Pointer to the SSH server context
420  * @param[in] callback Previously registered callback function
421  * @return Error code
422  **/
423 
425  SshChannelOpenCallback callback)
426 {
427  //Unregister channel open callback function
428  return sshUnregisterChannelOpenCallback(&context->sshContext, callback);
429 }
430 
431 
432 /**
433  * @brief Register connection open callback function
434  * @param[in] context Pointer to the SSH server context
435  * @param[in] callback Connection open callback function
436  * @param[in] param An opaque pointer passed to the callback function
437  * @return Error code
438  **/
439 
441  SshConnectionOpenCallback callback, void *param)
442 {
443  //Register connection open callback function
444  return sshRegisterConnectionOpenCallback(&context->sshContext, callback,
445  param);
446 }
447 
448 
449 /**
450  * @brief Unregister connection open callback function
451  * @param[in] context Pointer to the SSH server context
452  * @param[in] callback Previously registered callback function
453  * @return Error code
454  **/
455 
457  SshConnectionOpenCallback callback)
458 {
459  //Unregister connection open callback function
460  return sshUnregisterConnectionOpenCallback(&context->sshContext, callback);
461 }
462 
463 
464 /**
465  * @brief Register connection close callback function
466  * @param[in] context Pointer to the SSH server context
467  * @param[in] callback Connection close callback function
468  * @param[in] param An opaque pointer passed to the callback function
469  * @return Error code
470  **/
471 
473  SshConnectionCloseCallback callback, void *param)
474 {
475  //Register connection close callback function
476  return sshRegisterConnectionCloseCallback(&context->sshContext, callback,
477  param);
478 }
479 
480 
481 /**
482  * @brief Unregister connection close callback function
483  * @param[in] context Pointer to the SSH server context
484  * @param[in] callback Previously registered callback function
485  * @return Error code
486  **/
487 
490 {
491  //Unregister connection close callback function
492  return sshUnregisterConnectionCloseCallback(&context->sshContext, callback);
493 }
494 
495 
496 /**
497  * @brief Load transient RSA key (for RSA key exchange)
498  * @param[in] context Pointer to the SSH server context
499  * @param[in] index Zero-based index identifying a slot
500  * @param[in] publicKey RSA public key (PEM, SSH2 or OpenSSH format). This
501  * parameter is taken as reference
502  * @param[in] publicKeyLen Length of the RSA public key
503  * @param[in] privateKey RSA private key (PEM or OpenSSH format). This
504  * parameter is taken as reference
505  * @param[in] password NULL-terminated string containing the password. This
506  * parameter is required if the private key is encrypted
507  * @param[in] privateKeyLen Length of the RSA private key
508  * @return Error code
509  **/
510 
512  const char_t *publicKey, size_t publicKeyLen, const char_t *privateKey,
513  size_t privateKeyLen, const char_t *password)
514 {
515  //Load the specified transient RSA key
516  return sshLoadRsaKey(&context->sshContext, index, publicKey,
517  publicKeyLen, privateKey, privateKeyLen, password);
518 }
519 
520 
521 /**
522  * @brief Unload transient RSA key (for RSA key exchange)
523  * @param[in] context Pointer to the SSH server context
524  * @param[in] index Zero-based index identifying a slot
525  * @return Error code
526  **/
527 
529 {
530  //Unload the specified transient RSA key
531  return sshUnloadRsaKey(&context->sshContext, index);
532 }
533 
534 
535 /**
536  * @brief Load Diffie-Hellman group
537  * @param[in] context Pointer to the SSH server context
538  * @param[in] index Zero-based index identifying a slot
539  * @param[in] dhParams Diffie-Hellman parameters (PEM format). This parameter
540  * is taken as reference
541  * @param[in] dhParamsLen Length of the Diffie-Hellman parameters
542  * @return Error code
543  **/
544 
546  const char_t *dhParams, size_t dhParamsLen)
547 {
548  //Load the specified Diffie-Hellman group
549  return sshLoadDhGexGroup(&context->sshContext, index, dhParams,
550  dhParamsLen);
551 }
552 
553 
554 /**
555  * @brief Unload Diffie-Hellman group
556  * @param[in] context Pointer to the SSH server context
557  * @param[in] index Zero-based index identifying a slot
558  * @return Error code
559  **/
560 
562 {
563  //Unload the specified Diffie-Hellman group
564  return sshUnloadDhGexGroup(&context->sshContext, index);
565 }
566 
567 
568 /**
569  * @brief Load server's host key
570  * @param[in] context Pointer to the SSH server context
571  * @param[in] index Zero-based index identifying a slot
572  * @param[in] publicKey Public key (PEM, SSH2 or OpenSSH format). This parameter
573  * is taken as reference
574  * @param[in] publicKeyLen Length of the public key
575  * @param[in] privateKey Private key (PEM or OpenSSH format). This parameter is
576  * taken as reference
577  * @param[in] privateKeyLen Length of the private key
578  * @param[in] password NULL-terminated string containing the password. This
579  * parameter is required if the private key is encrypted
580  * @return Error code
581  **/
582 
584  const char_t *publicKey, size_t publicKeyLen, const char_t *privateKey,
585  size_t privateKeyLen, const char_t *password)
586 {
587  //Load the specified key pair
588  return sshLoadHostKey(&context->sshContext, index, publicKey, publicKeyLen,
589  privateKey, privateKeyLen, password);
590 }
591 
592 
593 /**
594  * @brief Unload server's host key
595  * @param[in] index Zero-based index identifying a slot
596  * @param[in] context Pointer to the SSH server context
597  * @return Error code
598  **/
599 
601 {
602  //Unload the specified key pair
603  return sshUnloadHostKey(&context->sshContext, index);
604 }
605 
606 
607 /**
608  * @brief Load server's certificate
609  * @param[in] context Pointer to the SSH server context
610  * @param[in] index Zero-based index identifying a slot
611  * @param[in] cert Certificate (OpenSSH format). This parameter is taken
612  * as reference
613  * @param[in] certLen Length of the certificate
614  * @param[in] privateKey Private key (PEM or OpenSSH format). This parameter
615  * is taken as reference
616  * @param[in] privateKeyLen Length of the private key
617  * @param[in] password NULL-terminated string containing the password. This
618  * parameter is required if the private key is encrypted
619  * @return Error code
620  **/
621 
623  const char_t *cert, size_t certLen, const char_t *privateKey,
624  size_t privateKeyLen, const char_t *password)
625 {
626 #if (SSH_CERT_SUPPORT == ENABLED)
627  //Load the specified certificate
628  return sshLoadCertificate(&context->sshContext, index, cert, certLen,
629  privateKey, privateKeyLen, password);
630 #else
631  //Not implemented
632  return ERROR_NOT_IMPLEMENTED;
633 #endif
634 }
635 
636 
637 /**
638  * @brief Unload server's certificate
639  * @param[in] index Zero-based index identifying a slot
640  * @param[in] context Pointer to the SSH server context
641  * @return Error code
642  **/
643 
645 {
646 #if (SSH_CERT_SUPPORT == ENABLED)
647  //Unload the specified certificate
648  return sshUnloadCertificate(&context->sshContext, index);
649 #else
650  //Not implemented
651  return ERROR_NOT_IMPLEMENTED;
652 #endif
653 }
654 
655 
656 /**
657  * @brief Start SSH server
658  * @param[in] context Pointer to the SSH server context
659  * @return Error code
660  **/
661 
663 {
664  error_t error;
665 
666  //Make sure the SSH server context is valid
667  if(context == NULL)
669 
670  //Debug message
671  TRACE_INFO("Starting SSH server...\r\n");
672 
673  //Make sure the SSH server is not already running
674  if(context->running)
675  return ERROR_ALREADY_RUNNING;
676 
677  //Start of exception handling block
678  do
679  {
680  //Open a TCP socket
681  context->socket = socketOpenEx(context->netContext, SOCKET_TYPE_STREAM,
683  //Failed to open socket?
684  if(context->socket == NULL)
685  {
686  //Report an error
687  error = ERROR_OPEN_FAILED;
688  //Exit immediately
689  break;
690  }
691 
692  //Force the socket to operate in non-blocking mode
693  error = socketSetTimeout(context->socket, 0);
694  //Any error to report?
695  if(error)
696  break;
697 
698  //Associate the socket with the relevant interface
699  error = socketBindToInterface(context->socket, context->interface);
700  //Any error to report?
701  if(error)
702  break;
703 
704  //The SSH server listens for connection requests on port 22
705  error = socketBind(context->socket, &IP_ADDR_ANY, context->port);
706  //Any error to report?
707  if(error)
708  break;
709 
710  //Place socket in listening state
711  error = socketListen(context->socket, 0);
712  //Any error to report?
713  if(error)
714  break;
715 
716  //Start the SSH server
717  context->stop = FALSE;
718  context->running = TRUE;
719 
720  //Create a task
721  context->taskId = osCreateTask("SSH Server", (OsTaskCode) sshServerTask,
722  context, &context->taskParams);
723 
724  //Failed to create task?
725  if(context->taskId == OS_INVALID_TASK_ID)
726  {
727  //Report an error
728  error = ERROR_OUT_OF_RESOURCES;
729  break;
730  }
731 
732  //End of exception handling block
733  } while(0);
734 
735  //Any error to report?
736  if(error)
737  {
738  //Clean up side effects
739  context->running = FALSE;
740 
741  //Close listening socket
742  socketClose(context->socket);
743  context->socket = NULL;
744  }
745 
746  //Return status code
747  return error;
748 }
749 
750 
751 /**
752  * @brief Stop SSH server
753  * @param[in] context Pointer to the SSH server context
754  * @return Error code
755  **/
756 
758 {
759  uint_t i;
760 
761  //Make sure the SSH server context is valid
762  if(context == NULL)
764 
765  //Debug message
766  TRACE_INFO("Stopping SSH server...\r\n");
767 
768  //Check whether the SSH server is running
769  if(context->running)
770  {
771 #if (NET_RTOS_SUPPORT == ENABLED)
772  //Stop the SSH server
773  context->stop = TRUE;
774  //Send a signal to the task to abort any blocking operation
775  sshNotifyEvent(&context->sshContext);
776 
777  //Wait for the task to terminate
778  while(context->running)
779  {
780  osDelayTask(1);
781  }
782 #endif
783 
784  //Loop through SSH connections
785  for(i = 0; i < context->sshContext.numConnections; i++)
786  {
787  //Active connection?
788  if(context->sshContext.connections[i].state != SSH_CONN_STATE_CLOSED)
789  {
790  //Close the SSH connection
791  sshCloseConnection(&context->sshContext.connections[i]);
792  }
793  }
794 
795  //Close listening socket
796  socketClose(context->socket);
797  context->socket = NULL;
798  }
799 
800  //Successful processing
801  return NO_ERROR;
802 }
803 
804 
805 /**
806  * @brief SSH server task
807  * @param[in] context Pointer to the SSH server context
808  **/
809 
811 {
812  error_t error;
813  uint_t i;
814  SshContext *sshContext;
815  SshConnection *connection;
816 
817  //Point to the SSH context
818  sshContext = &context->sshContext;
819 
820 #if (NET_RTOS_SUPPORT == ENABLED)
821  //Task prologue
822  osEnterTask();
823 
824  //Process events
825  while(1)
826  {
827 #endif
828  //Clear event descriptor set
829  osMemset(sshContext->eventDesc, 0, sizeof(sshContext->eventDesc));
830 
831  //Specify the events the application is interested in
832  for(i = 0; i < sshContext->numConnections; i++)
833  {
834  //Point to the structure describing the current connection
835  connection = &sshContext->connections[i];
836 
837  //Loop through active connections only
838  if(connection->state != SSH_CONN_STATE_CLOSED)
839  {
840  //Register the events related to the current SSH connection
841  sshRegisterConnectionEvents(sshContext, connection,
842  &sshContext->eventDesc[i]);
843  }
844  }
845 
846  //The SSH server listens for connection requests on port 22
847  sshContext->eventDesc[i].socket = context->socket;
848  sshContext->eventDesc[i].eventMask = SOCKET_EVENT_ACCEPT;
849 
850  //Wait for one of the set of sockets to become ready to perform I/O
851  error = socketPoll(sshContext->eventDesc, sshContext->numConnections + 1,
852  &sshContext->event, SSH_SERVER_TICK_INTERVAL);
853 
854  //Check status code
855  if(error == NO_ERROR || error == ERROR_TIMEOUT ||
856  error == ERROR_WAIT_CANCELED)
857  {
858  //Stop request?
859  if(context->stop)
860  {
861  //Stop SSH server operation
862  context->running = FALSE;
863  //Task epilogue
864  osExitTask();
865  //Kill ourselves
867  }
868 
869  //Event-driven processing
870  for(i = 0; i < sshContext->numConnections; i++)
871  {
872  //Point to the structure describing the current connection
873  connection = &sshContext->connections[i];
874 
875  //Loop through active connections only
876  if(connection->state != SSH_CONN_STATE_CLOSED)
877  {
878  //Check whether the socket is ready to perform I/O
879  if(sshContext->eventDesc[i].eventFlags != 0)
880  {
881  //Connection event handler
882  error = sshProcessConnectionEvents(sshContext, connection);
883 
884  //Any communication error?
885  if(error != NO_ERROR && error != ERROR_TIMEOUT)
886  {
887  //Close the SSH connection
888  sshCloseConnection(connection);
889  }
890  }
891  }
892  }
893 
894  //Any connection request received on port 22?
895  if(sshContext->eventDesc[i].eventFlags != 0)
896  {
897  //Accept connection request
898  sshServerAcceptConnection(context);
899  }
900  }
901 
902  //Handle periodic operations
903  sshServerTick(context);
904 
905 #if (NET_RTOS_SUPPORT == ENABLED)
906  }
907 #endif
908 }
909 
910 
911 /**
912  * @brief Release SSH server context
913  * @param[in] context Pointer to the SSH server context
914  **/
915 
917 {
918  //Make sure the SSH server context is valid
919  if(context != NULL)
920  {
921  //Close listening socket
922  socketClose(context->socket);
923 
924  //Release SSH context
925  sshDeinit(&context->sshContext);
926 
927  //Clear SSH server context
928  osMemset(context, 0, sizeof(SshServerContext));
929  }
930 }
931 
932 #endif
NetInterface * interface
Underlying network interface.
Definition: ssh_server.h:77
error_t(* SshChannelReqCallback)(SshChannel *channel, const SshString *type, const uint8_t *data, size_t length, void *param)
Channel request callback function.
Definition: ssh.h:1300
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:1344
#define SSH_SERVER_TICK_INTERVAL
Definition: ssh_server.h:58
error_t sshUnregisterConnectionOpenCallback(SshContext *context, SshConnectionOpenCallback callback)
Unregister connection open callback function.
Definition: ssh.c:926
#define osExitTask()
void(* SshConnectionCloseCallback)(SshConnection *connection, void *param)
Connection close callback function.
Definition: ssh.h:1325
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
SSH server settings.
Definition: ssh_server.h:74
error_t sshUnloadRsaKey(SshContext *context, uint_t index)
Unload transient RSA key (for RSA key exchange)
Definition: ssh.c:1197
bool_t stop
Stop request.
Definition: ssh_server.h:118
SshEcdhSharedSecretCalcCallback ecdhSharedSecretCalcCallback
ECDH shared secret calculation callback.
Definition: ssh_server.h:103
SshPublicKeyAuthCallback publicKeyAuthCallback
Public key authentication callback.
Definition: ssh_server.h:87
#define TRUE
Definition: os_port.h:50
error_t sshRegisterConnectionCloseCallback(SshContext *context, SshConnectionCloseCallback callback, void *param)
Register connection close callback function.
Definition: ssh.c:966
#define OS_INVALID_TASK_ID
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2094
error_t sshRegisterChannelRequestCallback(SshContext *context, SshChannelReqCallback callback, void *param)
Register channel request callback function.
Definition: ssh.c:705
error_t sshServerLoadRsaKey(SshServerContext *context, uint_t index, const char_t *publicKey, size_t publicKeyLen, const char_t *privateKey, size_t privateKeyLen, const char_t *password)
Load transient RSA key (for RSA key exchange)
Definition: ssh_server.c:511
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
SshEcdhKeyPairGenCallback ecdhKeyPairGenCallback
ECDH key pair generation callback.
Definition: ssh_server.h:102
error_t sshServerStart(SshServerContext *context)
Start SSH server.
Definition: ssh_server.c:662
error_t sshServerRegisterChannelRequestCallback(SshServerContext *context, SshChannelReqCallback callback, void *param)
Register channel request callback function.
Definition: ssh_server.c:376
#define SSH_PORT
Definition: ssh.h:878
error_t sshUnloadDhGexGroup(SshContext *context, uint_t index)
Unload Diffie-Hellman group.
Definition: ssh.c:1311
error_t sshServerUnregisterChannelRequestCallback(SshServerContext *context, SshChannelReqCallback callback)
Unregister channel request callback function.
Definition: ssh_server.c:392
error_t sshRegisterPasswordChangeCallback(SshContext *context, SshPasswordChangeCallback callback)
Register password change callback function.
Definition: ssh.c:462
error_t sshServerUnregisterChannelOpenCallback(SshServerContext *context, SshChannelOpenCallback callback)
Unregister channel open callback function.
Definition: ssh_server.c:424
SshSignVerifyCallback signVerifyCallback
Signature verification callback.
Definition: ssh_server.h:99
error_t sshServerUnregisterGlobalRequestCallback(SshServerContext *context, SshGlobalReqCallback callback)
Unregister global request callback function.
Definition: ssh_server.c:360
error_t sshRegisterEcdhSharedSecretCalcCallback(SshContext *context, SshEcdhSharedSecretCalcCallback callback)
Register ECDH shared secret calculation callback function.
Definition: ssh.c:586
@ SOCKET_TYPE_STREAM
Definition: socket.h:92
#define OS_SELF_TASK_ID
void sshServerTask(SshServerContext *context)
SSH server task.
Definition: ssh_server.c:810
error_t sshServerInit(SshServerContext *context, const SshServerSettings *settings)
Initialize SSH server context.
Definition: ssh_server.c:126
#define SSH_SERVER_TIMEOUT
Definition: ssh_server.h:51
error_t sshRegisterSignVerifyCallback(SshContext *context, SshSignVerifyCallback callback)
Register signature verification callback function.
Definition: ssh.c:524
error_t sshServerLoadCertificate(SshServerContext *context, uint_t index, const char_t *cert, size_t certLen, const char_t *privateKey, size_t privateKeyLen, const char_t *password)
Load server's certificate.
Definition: ssh_server.c:622
error_t sshInit(SshContext *context, SshConnection *connections, uint_t numConnections, SshChannel *channels, uint_t numChannels)
SSH context initialization.
Definition: ssh.c:58
error_t sshServerRegisterGlobalRequestCallback(SshServerContext *context, SshGlobalReqCallback callback, void *param)
Register global request callback function.
Definition: ssh_server.c:344
@ ERROR_OPEN_FAILED
Definition: error.h:75
error_t sshUnloadHostKey(SshContext *context, uint_t index)
Unload entity's host key.
Definition: ssh.c:1615
systime_t timeout
Idle connection timeout.
Definition: ssh_server.h:79
void sshServerTick(SshServerContext *context)
Handle periodic operations.
error_t sshRegisterConnectionOpenCallback(SshContext *context, SshConnectionOpenCallback callback, void *param)
Register connection open callback function.
Definition: ssh.c:879
error_t sshServerUnloadHostKey(SshServerContext *context, uint_t index)
Unload server's host key.
Definition: ssh_server.c:600
const IpAddr IP_ADDR_ANY
Definition: ip.c:53
error_t sshUnregisterConnectionCloseCallback(SshContext *context, SshConnectionCloseCallback callback)
Unregister connection close callback function.
Definition: ssh.c:1013
void osDeleteTask(OsTaskId taskId)
Delete a task.
error_t sshRegisterGlobalRequestCallback(SshContext *context, SshGlobalReqCallback callback, void *param)
Register global request callback function.
Definition: ssh.c:618
#define FALSE
Definition: os_port.h:46
systime_t timeout
Idle connection timeout.
Definition: ssh_server.h:125
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t sshServerUnregisterConnectionCloseCallback(SshServerContext *context, SshConnectionCloseCallback callback)
Unregister connection close callback function.
Definition: ssh_server.c:488
error_t sshServerRegisterChannelOpenCallback(SshServerContext *context, SshChannelOpenCallback callback, void *param)
Register channel open callback function.
Definition: ssh_server.c:408
#define SshContext
Definition: ssh.h:892
error_t sshRegisterCaPublicKeyVerifyCallback(SshContext *context, SshCaPublicKeyVerifyCallback callback)
Register CA public key verification callback function.
Definition: ssh.c:338
error_t
Error codes.
Definition: error.h:43
error_t sshRegisterChannelOpenCallback(SshContext *context, SshChannelOpenCallback callback, void *param)
Register channel open callback function.
Definition: ssh.c:792
void sshDeinit(SshContext *context)
Release SSH context.
Definition: ssh.c:2581
error_t sshUnloadCertificate(SshContext *context, uint_t index)
Unload entity's certificate.
Definition: ssh.c:1899
error_t(* SshGlobalReqCallback)(SshConnection *connection, const SshString *name, const uint8_t *data, size_t length, void *param)
Global request callback function.
Definition: ssh.h:1292
bool_t running
Operational state of the SSH server.
Definition: ssh_server.h:117
void sshServerAcceptConnection(SshServerContext *context)
Accept connection request.
void(* OsTaskCode)(void *arg)
Task routine.
uint_t numConnections
Maximum number of SSH connections.
Definition: ssh_server.h:80
@ SSH_OPERATION_MODE_SERVER
Definition: ssh.h:915
error_t(* SshChannelOpenCallback)(SshConnection *connection, const SshString *type, uint32_t senderChannel, uint32_t initialWindowSize, uint32_t maxPacketSize, const uint8_t *data, size_t length, void *param)
Channel open callback function.
Definition: ssh.h:1308
NetContext * netContext
TCP/IP stack context.
Definition: ssh_server.h:76
error_t sshRegisterCertAuthCallback(SshContext *context, SshCertAuthCallback callback)
Register certificate authentication callback function.
Definition: ssh.c:400
error_t sshLoadDhGexGroup(SshContext *context, uint_t index, const char_t *dhParams, size_t dhParamsLen)
Load Diffie-Hellman group.
Definition: ssh.c:1234
@ SOCKET_EVENT_ACCEPT
Definition: socket.h:172
error_t sshUnregisterChannelRequestCallback(SshContext *context, SshChannelReqCallback callback)
Unregister channel request callback function.
Definition: ssh.c:752
SshCaPublicKeyVerifyCallback caPublicKeyVerifyCallback
CA public key verification callback.
Definition: ssh_server.h:91
SSH server context.
Definition: ssh_server.h:116
error_t sshProcessConnectionEvents(SshContext *context, SshConnection *connection)
Connection event handler.
Definition: ssh_misc.c:375
void sshCloseConnection(SshConnection *connection)
Close SSH connection.
Definition: ssh_misc.c:174
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
#define SSH_SERVER_STACK_SIZE
Definition: ssh_server.h:39
OsTaskParameters task
Task parameters.
Definition: ssh_server.h:75
error_t sshServerLoadDhGexGroup(SshServerContext *context, uint_t index, const char_t *dhParams, size_t dhParamsLen)
Load Diffie-Hellman group.
Definition: ssh_server.c:545
void sshServerDeinit(SshServerContext *context)
Release SSH server context.
Definition: ssh_server.c:916
error_t sshRegisterKeyLogCallback(SshContext *context, SshKeyLogCallback callback)
Register key logging callback function (for debugging purpose only)
Definition: ssh.c:1052
error_t sshRegisterPasswordAuthCallback(SshContext *context, SshPasswordAuthCallback callback)
Register password authentication callback function.
Definition: ssh.c:431
error_t sshServerLoadHostKey(SshServerContext *context, uint_t index, const char_t *publicKey, size_t publicKeyLen, const char_t *privateKey, size_t privateKeyLen, const char_t *password)
Load server's host key.
Definition: ssh_server.c:583
void * prngContext
Pseudo-random number generator context.
Definition: ssh_server.h:85
#define TRACE_INFO(...)
Definition: debug.h:105
error_t sshRegisterSignGenCallback(SshContext *context, SshSignGenCallback callback)
Register signature generation callback function.
Definition: ssh.c:493
error_t sshServerUnloadRsaKey(SshServerContext *context, uint_t index)
Unload transient RSA key (for RSA key exchange)
Definition: ssh_server.c:528
#define osEnterTask()
error_t(* SshConnectionOpenCallback)(SshConnection *connection, void *param)
Connection open callback function.
Definition: ssh.h:1317
SshCertAuthCallback certAuthCallback
Certificate authentication callback.
Definition: ssh_server.h:90
@ SSH_CONN_STATE_CLOSED
Definition: ssh.h:1057
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:2182
#define socketBindToInterface
Definition: net_legacy.h:193
error_t sshRegisterEcdhKeyPairGenCallback(SshContext *context, SshEcdhKeyPairGenCallback callback)
Register ECDH key pair generation callback function.
Definition: ssh.c:555
Helper functions for SSH server.
void sshNotifyEvent(SshContext *context)
Notify the SSH context that event is occurring.
Definition: ssh_misc.c:721
error_t sshServerUnloadDhGexGroup(SshServerContext *context, uint_t index)
Unload Diffie-Hellman group.
Definition: ssh_server.c:561
#define SSH_MAX_CONNECTIONS
Definition: ssh.h:185
#define SSH_SERVER_PRIORITY
Definition: ssh_server.h:46
SshKeyLogCallback keyLogCallback
Key logging callback (for debugging purpose only)
Definition: ssh_server.h:106
uint16_t port
SSH port number.
Definition: ssh_server.h:78
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:55
OsTaskId taskId
Task identifier.
Definition: ssh_server.h:120
error_t sshUnregisterChannelOpenCallback(SshContext *context, SshChannelOpenCallback callback)
Unregister channel open callback function.
Definition: ssh.c:839
SshPasswordChangeCallback passwordChangeCallback
Password change callback.
Definition: ssh_server.h:95
error_t sshSetPrng(SshContext *context, const PrngAlgo *prngAlgo, void *prngContext)
Set the pseudo-random number generator to be used.
Definition: ssh.c:193
void sshRegisterConnectionEvents(SshContext *context, SshConnection *connection, SocketEventDesc *eventDesc)
Register connection events.
Definition: ssh_misc.c:282
#define SshConnection
Definition: ssh.h:896
Socket * socketOpenEx(NetContext *context, uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:146
SSH server.
error_t sshServerUnregisterConnectionOpenCallback(SshServerContext *context, SshConnectionOpenCallback callback)
Unregister connection open callback function.
Definition: ssh_server.c:456
SshConnection * connections
SSH connections.
Definition: ssh_server.h:81
@ ERROR_WAIT_CANCELED
Definition: error.h:73
SSH helper functions.
error_t sshServerUnloadCertificate(SshServerContext *context, uint_t index)
Unload server's certificate.
Definition: ssh_server.c:644
SshContext sshContext
SSH context.
Definition: ssh_server.h:126
SshPasswordAuthCallback passwordAuthCallback
Password authentication callback.
Definition: ssh_server.h:94
error_t sshRegisterPublicKeyAuthCallback(SshContext *context, SshPublicKeyAuthCallback callback)
Register public key authentication callback function.
Definition: ssh.c:369
void osDelayTask(systime_t delay)
Delay routine.
NetInterface * interface
Underlying network interface.
Definition: ssh_server.h:122
uint16_t port
SSH port number.
Definition: ssh_server.h:124
error_t sshServerRegisterConnectionCloseCallback(SshServerContext *context, SshConnectionCloseCallback callback, void *param)
Register connection close callback function.
Definition: ssh_server.c:472
uint_t numChannels
Maximum number of SSH channels.
Definition: ssh_server.h:82
SshSignGenCallback signGenCallback
Signature generation callback.
Definition: ssh_server.h:98
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t sshSetOperationMode(SshContext *context, SshOperationMode mode)
Set operation mode (client or server)
Definition: ssh.c:167
error_t sshServerRegisterConnectionOpenCallback(SshServerContext *context, SshConnectionOpenCallback callback, void *param)
Register connection open callback function.
Definition: ssh_server.c:440
error_t sshUnregisterGlobalRequestCallback(SshContext *context, SshGlobalReqCallback callback)
Unregister global request callback function.
Definition: ssh.c:665
Secure Shell (SSH)
NetContext * netContext
TCP/IP stack context.
Definition: ssh_server.h:121
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ssh_server.h:84
SshChannel * channels
SSH channels.
Definition: ssh_server.h:83
error_t sshLoadHostKey(SshContext *context, uint_t index, const char_t *publicKey, size_t publicKeyLen, const char_t *privateKey, size_t privateKeyLen, const char_t *password)
Load entity's host key.
Definition: ssh.c:1353
OsTaskParameters taskParams
Task parameters.
Definition: ssh_server.h:119
@ SOCKET_IP_PROTO_TCP
Definition: socket.h:107
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:169
Socket * socket
Listening socket.
Definition: ssh_server.h:123
void sshServerGetDefaultSettings(SshServerSettings *settings)
Initialize settings with default values.
Definition: ssh_server.c:50
error_t sshLoadCertificate(SshContext *context, uint_t index, const char_t *cert, size_t certLen, const char_t *privateKey, size_t privateKeyLen, const char_t *password)
Load entity's certificate.
Definition: ssh.c:1678
@ ERROR_ALREADY_RUNNING
Definition: error.h:294
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t sshLoadRsaKey(SshContext *context, uint_t index, const char_t *publicKey, size_t publicKeyLen, const char_t *privateKey, size_t privateKeyLen, const char_t *password)
Load transient RSA key (for RSA key exchange)
Definition: ssh.c:1087
error_t sshServerStop(SshServerContext *context)
Stop SSH server.
Definition: ssh_server.c:757
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:1441