1 /* This is a sample implementation of a libssh based SSH server */
2 /*
3 Copyright 2014 Audrius Butkevicius
4 
5 This file is part of the SSH Library
6 
7 You are free to copy this file, modify it in any way, consider it being public
8 domain. This does not apply to the rest of the library though, but it is
9 allowed to cut-and-paste working code from this file to any license of
10 program.
11 The goal is to show the API in action.
12 */
13 
14 #include "config.h"
15 
16 #include <libssh/callbacks.h>
17 #include <libssh/server.h>
18 
19 #include <poll.h>
20 #ifdef HAVE_ARGP_H
21 #include <argp.h>
22 #endif
23 #include <fcntl.h>
24 #ifdef HAVE_LIBUTIL_H
25 #include <libutil.h>
26 #endif
27 #ifdef HAVE_PTY_H
28 #include <pty.h>
29 #endif
30 #include <signal.h>
31 #include <stdlib.h>
32 #ifdef HAVE_UTMP_H
33 #include <utmp.h>
34 #endif
35 #ifdef HAVE_UTIL_H
36 #include <util.h>
37 #endif
38 #include <sys/ioctl.h>
39 #include <sys/wait.h>
40 #include <sys/stat.h>
41 #include <stdio.h>
42 
43 #ifndef KEYS_FOLDER
44 #ifdef _WIN32
45 #define KEYS_FOLDER
46 #else
47 #define KEYS_FOLDER "/etc/ssh/"
48 #endif
49 #endif
50 
51 #define USER "myuser"
52 #define PASS "mypassword"
53 #define BUF_SIZE 1048576
54 #define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
55 #define SFTP_SERVER_PATH "/usr/lib/sftp-server"
56 
57 static void set_default_keys(ssh_bind sshbind,
58                              int rsa_already_set,
59                              int dsa_already_set,
60                              int ecdsa_already_set) {
61     if (!rsa_already_set) {
62         ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
63                              KEYS_FOLDER "ssh_host_rsa_key");
64     }
65     if (!dsa_already_set) {
66         ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
67                              KEYS_FOLDER "ssh_host_dsa_key");
68     }
69     if (!ecdsa_already_set) {
70         ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
71                              KEYS_FOLDER "ssh_host_ecdsa_key");
72     }
73     ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
74                          KEYS_FOLDER "ssh_host_ed25519_key");
75 }
76 #define DEF_STR_SIZE 1024
77 char authorizedkeys[DEF_STR_SIZE] = {0};
78 #ifdef HAVE_ARGP_H
79 const char *argp_program_version = "libssh server example "
80 SSH_STRINGIFY(LIBSSH_VERSION);
81 const char *argp_program_bug_address = "<libssh@libssh.org>";
82 
83 /* Program documentation. */
84 static char doc[] = "libssh -- a Secure Shell protocol implementation";
85 
86 /* A description of the arguments we accept. */
87 static char args_doc[] = "BINDADDR";
88 
89 /* The options we understand. */
90 static struct argp_option options[] = {
91     {
92         .name  = "port",
93         .key   = 'p',
94         .arg   = "PORT",
95         .flags = 0,
96         .doc   = "Set the port to bind.",
97         .group = 0
98     },
99     {
100         .name  = "hostkey",
101         .key   = 'k',
102         .arg   = "FILE",
103         .flags = 0,
104         .doc   = "Set a host key.  Can be used multiple times.  "
105                  "Implies no default keys.",
106         .group = 0
107     },
108     {
109         .name  = "dsakey",
110         .key   = 'd',
111         .arg   = "FILE",
112         .flags = 0,
113         .doc   = "Set the dsa key.",
114         .group = 0
115     },
116     {
117         .name  = "rsakey",
118         .key   = 'r',
119         .arg   = "FILE",
120         .flags = 0,
121         .doc   = "Set the rsa key.",
122         .group = 0
123     },
124     {
125         .name  = "ecdsakey",
126         .key   = 'e',
127         .arg   = "FILE",
128         .flags = 0,
129         .doc   = "Set the ecdsa key.",
130         .group = 0
131     },
132     {
133         .name  = "authorizedkeys",
134         .key   = 'a',
135         .arg   = "FILE",
136         .flags = 0,
137         .doc   = "Set the authorized keys file.",
138         .group = 0
139     },
140     {
141         .name  = "no-default-keys",
142         .key   = 'n',
143         .arg   = NULL,
144         .flags = 0,
145         .doc   = "Do not set default key locations.",
146         .group = 0
147     },
148     {
149         .name  = "verbose",
150         .key   = 'v',
151         .arg   = NULL,
152         .flags = 0,
153         .doc   = "Get verbose output.",
154         .group = 0
155     },
156     {NULL, 0, NULL, 0, NULL, 0}
157 };
158 
159 /* Parse a single option. */
160 static error_t parse_opt (int key, char *arg, struct argp_state *state) {
161     /* Get the input argument from argp_parse, which we
162      * know is a pointer to our arguments structure. */
163     ssh_bind sshbind = state->input;
164     static int no_default_keys = 0;
165     static int rsa_already_set = 0, dsa_already_set = 0, ecdsa_already_set = 0;
166 
167     switch (key) {
168         case 'n':
169             no_default_keys = 1;
170             break;
171         case 'p':
172             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
173             break;
174         case 'd':
175             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
176             dsa_already_set = 1;
177             break;
178         case 'k':
179             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
180             /* We can't track the types of keys being added with this
181                option, so let's ensure we keep the keys we're adding
182                by just not setting the default keys */
183             no_default_keys = 1;
184             break;
185         case 'r':
186             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
187             rsa_already_set = 1;
188             break;
189         case 'e':
190             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg);
191             ecdsa_already_set = 1;
192             break;
193         case 'a':
194             strncpy(authorizedkeys, arg, DEF_STR_SIZE-1);
195             break;
196         case 'v':
197             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
198                                  "3");
199             break;
200         case ARGP_KEY_ARG:
201             if (state->arg_num >= 1) {
202                 /* Too many arguments. */
203                 argp_usage (state);
204             }
205             ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
206             break;
207         case ARGP_KEY_END:
208             if (state->arg_num < 1) {
209                 /* Not enough arguments. */
210                 argp_usage (state);
211             }
212 
213             if (!no_default_keys) {
214                 set_default_keys(sshbind,
215                                  rsa_already_set,
216                                  dsa_already_set,
217                                  ecdsa_already_set);
218             }
219 
220             break;
221         default:
222             return ARGP_ERR_UNKNOWN;
223     }
224     return 0;
225 }
226 
227 /* Our argp parser. */
228 static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
229 #endif /* HAVE_ARGP_H */
230 
231 /* A userdata struct for channel. */
232 struct channel_data_struct {
233     /* pid of the child process the channel will spawn. */
234     pid_t pid;
235     /* For PTY allocation */
236     socket_t pty_master;
237     socket_t pty_slave;
238     /* For communication with the child process. */
239     socket_t child_stdin;
240     socket_t child_stdout;
241     /* Only used for subsystem and exec requests. */
242     socket_t child_stderr;
243     /* Event which is used to poll the above descriptors. */
244     ssh_event event;
245     /* Terminal size struct. */
246     struct winsize *winsize;
247 };
248 
249 /* A userdata struct for session. */
250 struct session_data_struct {
251     /* Pointer to the channel the session will allocate. */
252     ssh_channel channel;
253     int auth_attempts;
254     int authenticated;
255 };
256 
257 static int data_function(ssh_session session, ssh_channel channel, void *data,
258                          uint32_t len, int is_stderr, void *userdata) {
259     struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
260 
261     (void) session;
262     (void) channel;
263     (void) is_stderr;
264 
265     if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) {
266         return 0;
267     }
268 
269     return write(cdata->child_stdin, (char *) data, len);
270 }
271 
272 static int pty_request(ssh_session session, ssh_channel channel,
273                        const char *term, int cols, int rows, int py, int px,
274                        void *userdata) {
275     struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
276 
277     (void) session;
278     (void) channel;
279     (void) term;
280 
281     cdata->winsize->ws_row = rows;
282     cdata->winsize->ws_col = cols;
283     cdata->winsize->ws_xpixel = px;
284     cdata->winsize->ws_ypixel = py;
285 
286     if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL,
287                 cdata->winsize) != 0) {
288         fprintf(stderr, "Failed to open pty\n");
289         return SSH_ERROR;
290     }
291     return SSH_OK;
292 }
293 
294 static int pty_resize(ssh_session session, ssh_channel channel, int cols,
295                       int rows, int py, int px, void *userdata) {
296     struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
297 
298     (void) session;
299     (void) channel;
300 
301     cdata->winsize->ws_row = rows;
302     cdata->winsize->ws_col = cols;
303     cdata->winsize->ws_xpixel = px;
304     cdata->winsize->ws_ypixel = py;
305 
306     if (cdata->pty_master != -1) {
307         return ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize);
308     }
309 
310     return SSH_ERROR;
311 }
312 
313 static int exec_pty(const char *mode, const char *command,
314                     struct channel_data_struct *cdata) {
315     switch(cdata->pid = fork()) {
316         case -1:
317             close(cdata->pty_master);
318             close(cdata->pty_slave);
319             fprintf(stderr, "Failed to fork\n");
320             return SSH_ERROR;
321         case 0:
322             close(cdata->pty_master);
323             if (login_tty(cdata->pty_slave) != 0) {
324                 exit(1);
325             }
326             execl("/bin/sh", "sh", mode, command, NULL);
327             exit(0);
328         default:
329             close(cdata->pty_slave);
330             /* pty fd is bi-directional */
331             cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
332     }
333     return SSH_OK;
334 }
335 
336 static int exec_nopty(const char *command, struct channel_data_struct *cdata) {
337     int in[2], out[2], err[2];
338 
339     /* Do the plumbing to be able to talk with the child process. */
340     if (pipe(in) != 0) {
341         goto stdin_failed;
342     }
343     if (pipe(out) != 0) {
344         goto stdout_failed;
345     }
346     if (pipe(err) != 0) {
347         goto stderr_failed;
348     }
349 
350     switch(cdata->pid = fork()) {
351         case -1:
352             goto fork_failed;
353         case 0:
354             /* Finish the plumbing in the child process. */
355             close(in[1]);
356             close(out[0]);
357             close(err[0]);
358             dup2(in[0], STDIN_FILENO);
359             dup2(out[1], STDOUT_FILENO);
360             dup2(err[1], STDERR_FILENO);
361             close(in[0]);
362             close(out[1]);
363             close(err[1]);
364             /* exec the requested command. */
365             execl("/bin/sh", "sh", "-c", command, NULL);
366             exit(0);
367     }
368 
369     close(in[0]);
370     close(out[1]);
371     close(err[1]);
372 
373     cdata->child_stdin = in[1];
374     cdata->child_stdout = out[0];
375     cdata->child_stderr = err[0];
376 
377     return SSH_OK;
378 
379 fork_failed:
380     close(err[0]);
381     close(err[1]);
382 stderr_failed:
383     close(out[0]);
384     close(out[1]);
385 stdout_failed:
386     close(in[0]);
387     close(in[1]);
388 stdin_failed:
389     return SSH_ERROR;
390 }
391 
392 static int exec_request(ssh_session session, ssh_channel channel,
393                         const char *command, void *userdata) {
394     struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
395 
396 
397     (void) session;
398     (void) channel;
399 
400     if(cdata->pid > 0) {
401         return SSH_ERROR;
402     }
403 
404     if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
405         return exec_pty("-c", command, cdata);
406     }
407     return exec_nopty(command, cdata);
408 }
409 
410 static int shell_request(ssh_session session, ssh_channel channel,
411                          void *userdata) {
412     struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
413 
414     (void) session;
415     (void) channel;
416 
417     if(cdata->pid > 0) {
418         return SSH_ERROR;
419     }
420 
421     if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
422         return exec_pty("-l", NULL, cdata);
423     }
424     /* Client requested a shell without a pty, let's pretend we allow that */
425     return SSH_OK;
426 }
427 
428 static int subsystem_request(ssh_session session, ssh_channel channel,
429                              const char *subsystem, void *userdata) {
430     /* subsystem requests behave simillarly to exec requests. */
431     if (strcmp(subsystem, "sftp") == 0) {
432         return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
433     }
434     return SSH_ERROR;
435 }
436 
437 static int auth_password(ssh_session session, const char *user,
438                          const char *pass, void *userdata) {
439     struct session_data_struct *sdata = (struct session_data_struct *) userdata;
440 
441     (void) session;
442 
443     if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) {
444         sdata->authenticated = 1;
445         return SSH_AUTH_SUCCESS;
446     }
447 
448     sdata->auth_attempts++;
449     return SSH_AUTH_DENIED;
450 }
451 
452 static int auth_publickey(ssh_session session,
453                           const char *user,
454                           struct ssh_key_struct *pubkey,
455                           char signature_state,
456                           void *userdata)
457 {
458     struct session_data_struct *sdata = (struct session_data_struct *) userdata;
459 
460     (void) user;
461     (void) session;
462 
463     if (signature_state == SSH_PUBLICKEY_STATE_NONE) {
464         return SSH_AUTH_SUCCESS;
465     }
466 
467     if (signature_state != SSH_PUBLICKEY_STATE_VALID) {
468         return SSH_AUTH_DENIED;
469     }
470 
471     // valid so far.  Now look through authorized keys for a match
472     if (authorizedkeys[0]) {
473         ssh_key key = NULL;
474         int result;
475         struct stat buf;
476 
477         if (stat(authorizedkeys, &buf) == 0) {
478             result = ssh_pki_import_pubkey_file( authorizedkeys, &key );
479             if ((result != SSH_OK) || (key==NULL)) {
480                 fprintf(stderr,
481                         "Unable to import public key file %s\n",
482                         authorizedkeys);
483             } else {
484                 result = ssh_key_cmp( key, pubkey, SSH_KEY_CMP_PUBLIC );
485                 ssh_key_free(key);
486                 if (result == 0) {
487                     sdata->authenticated = 1;
488                     return SSH_AUTH_SUCCESS;
489                 }
490             }
491         }
492     }
493 
494     // no matches
495     sdata->authenticated = 0;
496     return SSH_AUTH_DENIED;
497 }
498 
499 static ssh_channel channel_open(ssh_session session, void *userdata) {
500     struct session_data_struct *sdata = (struct session_data_struct *) userdata;
501 
502     sdata->channel = ssh_channel_new(session);
503     return sdata->channel;
504 }
505 
506 static int process_stdout(socket_t fd, int revents, void *userdata) {
507     char buf[BUF_SIZE];
508     int n = -1;
509     ssh_channel channel = (ssh_channel) userdata;
510 
511     if (channel != NULL && (revents & POLLIN) != 0) {
512         n = read(fd, buf, BUF_SIZE);
513         if (n > 0) {
514             ssh_channel_write(channel, buf, n);
515         }
516     }
517 
518     return n;
519 }
520 
521 static int process_stderr(socket_t fd, int revents, void *userdata) {
522     char buf[BUF_SIZE];
523     int n = -1;
524     ssh_channel channel = (ssh_channel) userdata;
525 
526     if (channel != NULL && (revents & POLLIN) != 0) {
527         n = read(fd, buf, BUF_SIZE);
528         if (n > 0) {
529             ssh_channel_write_stderr(channel, buf, n);
530         }
531     }
532 
533     return n;
534 }
535 
536 static void handle_session(ssh_event event, ssh_session session) {
537     int n;
538     int rc = 0;
539 
540     /* Structure for storing the pty size. */
541     struct winsize wsize = {
542         .ws_row = 0,
543         .ws_col = 0,
544         .ws_xpixel = 0,
545         .ws_ypixel = 0
546     };
547 
548     /* Our struct holding information about the channel. */
549     struct channel_data_struct cdata = {
550         .pid = 0,
551         .pty_master = -1,
552         .pty_slave = -1,
553         .child_stdin = -1,
554         .child_stdout = -1,
555         .child_stderr = -1,
556         .event = NULL,
557         .winsize = &wsize
558     };
559 
560     /* Our struct holding information about the session. */
561     struct session_data_struct sdata = {
562         .channel = NULL,
563         .auth_attempts = 0,
564         .authenticated = 0
565     };
566 
567     struct ssh_channel_callbacks_struct channel_cb = {
568         .userdata = &cdata,
569         .channel_pty_request_function = pty_request,
570         .channel_pty_window_change_function = pty_resize,
571         .channel_shell_request_function = shell_request,
572         .channel_exec_request_function = exec_request,
573         .channel_data_function = data_function,
574         .channel_subsystem_request_function = subsystem_request
575     };
576 
577     struct ssh_server_callbacks_struct server_cb = {
578         .userdata = &sdata,
579         .auth_password_function = auth_password,
580         .channel_open_request_session_function = channel_open,
581     };
582 
583     if (authorizedkeys[0]) {
584         server_cb.auth_pubkey_function = auth_publickey;
585         ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY);
586     } else
587         ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
588 
589     ssh_callbacks_init(&server_cb);
590     ssh_callbacks_init(&channel_cb);
591 
592     ssh_set_server_callbacks(session, &server_cb);
593 
594     if (ssh_handle_key_exchange(session) != SSH_OK) {
595         fprintf(stderr, "%s\n", ssh_get_error(session));
596         return;
597     }
598 
599     ssh_event_add_session(event, session);
600 
601     n = 0;
602     while (sdata.authenticated == 0 || sdata.channel == NULL) {
603         /* If the user has used up all attempts, or if he hasn't been able to
604          * authenticate in 10 seconds (n * 100ms), disconnect. */
605         if (sdata.auth_attempts >= 3 || n >= 100) {
606             return;
607         }
608 
609         if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
610             fprintf(stderr, "%s\n", ssh_get_error(session));
611             return;
612         }
613         n++;
614     }
615 
616     ssh_set_channel_callbacks(sdata.channel, &channel_cb);
617 
618     do {
619         /* Poll the main event which takes care of the session, the channel and
620          * even our child process's stdout/stderr (once it's started). */
621         if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
622           ssh_channel_close(sdata.channel);
623         }
624 
625         /* If child process's stdout/stderr has been registered with the event,
626          * or the child process hasn't started yet, continue. */
627         if (cdata.event != NULL || cdata.pid == 0) {
628             continue;
629         }
630         /* Executed only once, once the child process starts. */
631         cdata.event = event;
632         /* If stdout valid, add stdout to be monitored by the poll event. */
633         if (cdata.child_stdout != -1) {
634             if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout,
635                                  sdata.channel) != SSH_OK) {
636                 fprintf(stderr, "Failed to register stdout to poll context\n");
637                 ssh_channel_close(sdata.channel);
638             }
639         }
640 
641         /* If stderr valid, add stderr to be monitored by the poll event. */
642         if (cdata.child_stderr != -1){
643             if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr,
644                                  sdata.channel) != SSH_OK) {
645                 fprintf(stderr, "Failed to register stderr to poll context\n");
646                 ssh_channel_close(sdata.channel);
647             }
648         }
649     } while(ssh_channel_is_open(sdata.channel) &&
650             (cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
651 
652     close(cdata.pty_master);
653     close(cdata.child_stdin);
654     close(cdata.child_stdout);
655     close(cdata.child_stderr);
656 
657     /* Remove the descriptors from the polling context, since they are now
658      * closed, they will always trigger during the poll calls. */
659     ssh_event_remove_fd(event, cdata.child_stdout);
660     ssh_event_remove_fd(event, cdata.child_stderr);
661 
662     /* If the child process exited. */
663     if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) {
664         rc = WEXITSTATUS(rc);
665         ssh_channel_request_send_exit_status(sdata.channel, rc);
666     /* If client terminated the channel or the process did not exit nicely,
667      * but only if something has been forked. */
668     } else if (cdata.pid > 0) {
669         kill(cdata.pid, SIGKILL);
670     }
671 
672     ssh_channel_send_eof(sdata.channel);
673     ssh_channel_close(sdata.channel);
674 
675     /* Wait up to 5 seconds for the client to terminate the session. */
676     for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) {
677         ssh_event_dopoll(event, 100);
678     }
679 }
680 
681 /* SIGCHLD handler for cleaning up dead children. */
682 static void sigchld_handler(int signo) {
683     (void) signo;
684     while (waitpid(-1, NULL, WNOHANG) > 0);
685 }
686 
687 int main(int argc, char **argv) {
688     ssh_bind sshbind;
689     ssh_session session;
690     ssh_event event;
691     struct sigaction sa;
692     int rc;
693 
694     /* Set up SIGCHLD handler. */
695     sa.sa_handler = sigchld_handler;
696     sigemptyset(&sa.sa_mask);
697     sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
698     if (sigaction(SIGCHLD, &sa, NULL) != 0) {
699         fprintf(stderr, "Failed to register SIGCHLD handler\n");
700         return 1;
701     }
702 
703     rc = ssh_init();
704     if (rc < 0) {
705         fprintf(stderr, "ssh_init failed\n");
706         return 1;
707     }
708 
709     sshbind = ssh_bind_new();
710     if (sshbind == NULL) {
711         fprintf(stderr, "ssh_bind_new failed\n");
712         return 1;
713     }
714 
715 #ifdef HAVE_ARGP_H
716     argp_parse(&argp, argc, argv, 0, 0, sshbind);
717 #else
718     (void) argc;
719     (void) argv;
720 
721     set_default_keys(sshbind, 0, 0, 0);
722 #endif /* HAVE_ARGP_H */
723 
724     if(ssh_bind_listen(sshbind) < 0) {
725         fprintf(stderr, "%s\n", ssh_get_error(sshbind));
726         return 1;
727     }
728 
729     while (1) {
730         session = ssh_new();
731         if (session == NULL) {
732             fprintf(stderr, "Failed to allocate session\n");
733             continue;
734         }
735 
736         /* Blocks until there is a new incoming connection. */
737         if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
738             switch(fork()) {
739                 case 0:
740                     /* Remove the SIGCHLD handler inherited from parent. */
741                     sa.sa_handler = SIG_DFL;
742                     sigaction(SIGCHLD, &sa, NULL);
743                     /* Remove socket binding, which allows us to restart the
744                      * parent process, without terminating existing sessions. */
745                     ssh_bind_free(sshbind);
746 
747                     event = ssh_event_new();
748                     if (event != NULL) {
749                         /* Blocks until the SSH session ends by either
750                          * child process exiting, or client disconnecting. */
751                         handle_session(event, session);
752                         ssh_event_free(event);
753                     } else {
754                         fprintf(stderr, "Could not create polling context\n");
755                     }
756                     ssh_disconnect(session);
757                     ssh_free(session);
758 
759                     exit(0);
760                 case -1:
761                     fprintf(stderr, "Failed to fork\n");
762             }
763         } else {
764             fprintf(stderr, "%s\n", ssh_get_error(sshbind));
765         }
766         /* Since the session has been passed to a child fork, do some cleaning
767          * up at the parent process. */
768         ssh_disconnect(session);
769         ssh_free(session);
770     }
771 
772     ssh_bind_free(sshbind);
773     ssh_finalize();
774     return 0;
775 }
776