aboutsummaryrefslogtreecommitdiff
path: root/src/server_ssh.c
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2018-04-21 20:48:28 +0200
committerToni Uhlig <matzeton@googlemail.com>2018-04-21 20:48:28 +0200
commiteec5b667ca019f7a334475f58c37ebcd1ea6078c (patch)
treeec249922372cffbd009081eae4f2298bb2b1a68f /src/server_ssh.c
parent44bb4bb4c68724d52a014425b6bbcec1c0f45274 (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.c113
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);
+}