diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-04-21 20:48:28 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-04-21 20:48:28 +0200 |
commit | eec5b667ca019f7a334475f58c37ebcd1ea6078c (patch) | |
tree | ec249922372cffbd009081eae4f2298bb2b1a68f /src/server_ssh.c | |
parent | 44bb4bb4c68724d52a014425b6bbcec1c0f45274 (diff) |
POTD skeleton #21.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'src/server_ssh.c')
-rw-r--r-- | src/server_ssh.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/server_ssh.c b/src/server_ssh.c index 7082f70..c84f718 100644 --- a/src/server_ssh.c +++ b/src/server_ssh.c @@ -38,6 +38,18 @@ static void * ssh_thread_mainloop(void *arg); static int authenticate(ssh_session session); static int auth_password(const char *user, const char *password); +static int main_loop(ssh_channel chan); +static int copy_fd_to_chan(socket_t fd, int revents, void *userdata); +static int copy_chan_to_fd(ssh_session session, ssh_channel channel, void *data, + uint32_t len, int is_stderr, void *userdata); +static void chan_close(ssh_session session, ssh_channel channel, void *userdata); + +struct ssh_channel_callbacks_struct ssh_channel_cb = { + .channel_data_function = copy_chan_to_fd, + .channel_eof_function = chan_close, + .channel_close_function = chan_close, + .userdata = NULL +}; int ssh_init_cb(struct forward_ctx *ctx) @@ -313,6 +325,9 @@ ssh_thread_mainloop(void *arg) goto failed; } + N("%s", "Dropping user into shell"); + main_loop(chan); + failed: ssh_disconnect(ses); ssh_free(ses); @@ -387,3 +402,101 @@ static int auth_password(const char *user, const char *password) */ return 1; /* authenticated */ } + +static int main_loop(ssh_channel chan) +{ + ssh_session session = ssh_channel_get_session(chan); + socket_t fd; + struct termios *term = NULL; + struct winsize *win = NULL; + pid_t childpid; + ssh_event event; + short events; + + childpid = forkpty(&fd, NULL, term, win); + if (childpid == 0) { + execl("/bin/bash", "/bin/bash", (char *)NULL); + abort(); + } + + ssh_channel_cb.userdata = &fd; + ssh_callbacks_init(&ssh_channel_cb); + ssh_set_channel_callbacks(chan, &ssh_channel_cb); + + events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; + + event = ssh_event_new(); + if (event == NULL) { + printf("Couldn't get a event\n"); + return -1; + } + if (ssh_event_add_fd(event, fd, events, copy_fd_to_chan, chan) != SSH_OK) { + printf("Couldn't add an fd to the event\n"); + return -1; + } + if (ssh_event_add_session(event, session) != SSH_OK) { + printf("Couldn't add the session to the event\n"); + return -1; + } + + do { + ssh_event_dopoll(event, 1000); + } while(!ssh_channel_is_closed(chan)); + + ssh_event_remove_fd(event, fd); + + ssh_event_remove_session(event, session); + + ssh_event_free(event); + return 0; +} + +static int copy_fd_to_chan(socket_t fd, int revents, void *userdata) +{ + ssh_channel chan = (ssh_channel)userdata; + char buf[BUFSIZ]; + int sz = 0; + + if(!chan) { + close(fd); + return -1; + } + if(revents & POLLIN) { + sz = read(fd, buf, BUFSIZ); + if(sz > 0) { + ssh_channel_write(chan, buf, sz); + } + } + if(revents & POLLHUP) { + ssh_channel_close(chan); + sz = -1; + } + return sz; +} + +static int copy_chan_to_fd(ssh_session session, + ssh_channel channel, + void *data, + uint32_t len, + int is_stderr, + void *userdata) +{ + int fd = *(int*)userdata; + int sz; + (void)session; + (void)channel; + (void)is_stderr; + + sz = write(fd, data, len); + return sz; +} + +static void chan_close(ssh_session session, ssh_channel channel, + void *userdata) +{ + int fd = *(int*)userdata; + (void)session; + (void)channel; + + close(fd); +} |