aboutsummaryrefslogtreecommitdiff
path: root/src/protocol_ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol_ssh.c')
-rw-r--r--src/protocol_ssh.c96
1 files changed, 71 insertions, 25 deletions
diff --git a/src/protocol_ssh.c b/src/protocol_ssh.c
index 0af4986..9d2be46 100644
--- a/src/protocol_ssh.c
+++ b/src/protocol_ssh.c
@@ -53,6 +53,7 @@
#include "protocol_ssh.h"
#include "protocol.h"
+#include "jail_packet.h"
#ifdef HAVE_SECCOMP
#include "pseccomp.h"
#endif
@@ -65,8 +66,6 @@
LIBSSH_VERSION_MICRO < 3
#pragma message "Unsupported libssh version < 0.7.3"
#endif
-#define USER_LEN LOGIN_NAME_MAX
-#define PASS_LEN 80
#define CACHE_MAX 32
#define CACHE_TIME (60 * 20) /* max cache time 20 minutes */
#define LOGIN_SUCCESS_PROB ((double)1/4) /* successful login probability */
@@ -86,6 +85,15 @@ typedef struct ssh_client {
forward_ctx dst;
} ssh_client;
+typedef struct ssh_userdata {
+ jail_packet_ctx *pkt_ctx;
+ ssh_client *client;
+ event_ctx *ev_ctx;
+ event_buf proto_read;
+ event_buf proto_fd;
+ event_buf proto_chan;
+} ssh_userdata;
+
struct protocol_cbs potd_ssh_callbacks = {
.on_listen = ssh_on_listen,
.on_shutdown = ssh_on_shutdown
@@ -108,10 +116,11 @@ static void ssh_log_cb(int priority, const char *function, const char *buffer,
void *userdata);
static void ssh_mainloop(ssh_data *arg)
__attribute__((noreturn));
-static int authenticate(ssh_session session, ssh_login_cache *cache);
+static int authenticate(ssh_session session, ssh_login_cache *cache,
+ jail_packet_ctx *pkt_ctx);
static int auth_password(const char *user, const char *pass,
ssh_login_cache *cache);
-static int client_mainloop(ssh_client *arg);
+static int client_mainloop(ssh_client *arg, jail_packet_ctx *ctx);
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);
@@ -432,6 +441,7 @@ static void ssh_mainloop(ssh_data *arg)
{
pthread_mutexattr_t shared;
ssh_login_cache *cache = NULL;
+ jail_packet_ctx pkt_ctx = INIT_PKTCTX(NULL,NULL);
size_t i;
int s, auth = 0, shell = 0, is_child;
ssh_session ses;
@@ -488,7 +498,7 @@ static void ssh_mainloop(ssh_data *arg)
}
/* proceed to authentication */
- auth = authenticate(ses, cache);
+ auth = authenticate(ses, cache, &pkt_ctx);
if (!auth) {
W("SSH authentication error: %s", ssh_get_error(ses));
goto failed;
@@ -551,7 +561,7 @@ static void ssh_mainloop(ssh_data *arg)
data.chan = chan;
data.dst = arg->ctx->dst;
- if (client_mainloop(&data))
+ if (client_mainloop(&data, &pkt_ctx))
W2("Client mainloop for fd %d failed",
ssh_bind_get_fd(arg->sshbind));
@@ -563,7 +573,8 @@ failed:
}
}
-static int authenticate(ssh_session session, ssh_login_cache *cache)
+static int authenticate(ssh_session session, ssh_login_cache *cache,
+ jail_packet_ctx *pkt_ctx)
{
ssh_message message;
ssh_key pubkey;
@@ -588,6 +599,8 @@ static int authenticate(ssh_session session, ssh_login_cache *cache)
if (auth_password(ssh_message_auth_user(message),
ssh_message_auth_password(message), cache))
{
+ pkt_ctx->user = strdup(ssh_message_auth_user(message));
+ pkt_ctx->pass = strdup(ssh_message_auth_password(message));
ssh_message_auth_reply_success(message,0);
ssh_message_free(message);
return 1;
@@ -737,13 +750,16 @@ static int auth_password(const char *user, const char *pass,
return got_auth;
}
-static int client_mainloop(ssh_client *data)
+static int client_mainloop(ssh_client *data, jail_packet_ctx *pkt_ctx)
{
ssh_channel chan = data->chan;
ssh_session session = ssh_channel_get_session(chan);
+ ssh_userdata userdata = { pkt_ctx, data, NULL,
+ EMPTY_BUF, EMPTY_BUF, EMPTY_BUF };
ssh_event event;
short events;
forward_ctx *ctx = &data->dst;
+ struct event_ctx *ev_ctx;
if (fwd_connect_sock(ctx, NULL)) {
E_STRERR("Connection to %s:%s",
@@ -752,7 +768,25 @@ static int client_mainloop(ssh_client *data)
return 1;
}
- ssh_channel_cb.userdata = &ctx->sock.fd;
+ ev_ctx = jail_client_handshake(ctx->sock.fd, pkt_ctx);
+ if (!ev_ctx) {
+ ssh_channel_close(chan);
+ return 1;
+ }
+
+ pkt_ctx->connection.client_fd = pkt_ctx->writeback_buf.fd =
+ userdata.proto_read.fd = ctx->sock.fd;
+ if (jail_client_data(ev_ctx, &userdata.proto_read,
+ &userdata.proto_chan, pkt_ctx))
+ {
+ ssh_channel_close(chan);
+ event_free(&ev_ctx);
+ return 1;
+ }
+ pkt_ctx->ev_readloop = 0;
+
+ userdata.ev_ctx = ev_ctx;
+ ssh_channel_cb.userdata = &userdata;
ssh_callbacks_init(&ssh_channel_cb);
ssh_set_channel_callbacks(chan, &ssh_channel_cb);
@@ -761,14 +795,19 @@ static int client_mainloop(ssh_client *data)
if (event == NULL) {
E2("%s", "Couldn't get a event");
+ event_free(&ev_ctx);
return 1;
}
- if (ssh_event_add_fd(event, ctx->sock.fd, events, copy_fd_to_chan, chan) != SSH_OK) {
+ if (ssh_event_add_fd(event, ctx->sock.fd, events, copy_fd_to_chan,
+ &userdata) != SSH_OK)
+ {
E2("Couldn't add fd %d to the event queue", ctx->sock.fd);
+ event_free(&ev_ctx);
return 1;
}
if (ssh_event_add_session(event, session) != SSH_OK) {
E2("%s", "Couldn't add the session to the event");
+ event_free(&ev_ctx);
return 1;
}
@@ -780,26 +819,34 @@ static int client_mainloop(ssh_client *data)
ssh_event_remove_fd(event, ctx->sock.fd);
ssh_event_remove_session(event, session);
ssh_event_free(event);
+ event_free(&ev_ctx);
+
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;
+ ssh_userdata *sudata = (ssh_userdata *) userdata;
+ ssh_channel chan = sudata->client->chan;
+ ssize_t sz = 0;
+ int written;
- if(!chan) {
+ 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 & POLLIN) {
+ sz = event_buf_read(&sudata->proto_read);
+ if (sz > 0 &&
+ !jail_client_data(sudata->ev_ctx, &sudata->proto_read,
+ &sudata->proto_chan, sudata->pkt_ctx))
+ {
+ written = ssh_channel_write(chan, sudata->proto_chan.buf,
+ sudata->proto_chan.buf_used);
+ event_buf_discard(&sudata->proto_chan, written);
}
}
- if(revents & POLLHUP || sz <= 0) {
+ if (revents & POLLHUP || sz <= 0) {
ssh_channel_close(chan);
sz = -1;
}
@@ -814,23 +861,22 @@ static int copy_chan_to_fd(ssh_session session,
int is_stderr,
void *userdata)
{
- int fd = *(int*) userdata;
- int sz;
+ ssh_userdata *sudata = (ssh_userdata *) userdata;
(void) session;
(void) is_stderr;
- sz = write(fd, data, len);
- if (sz <= 0)
+ if (jail_client_send(sudata->pkt_ctx, data, len))
ssh_channel_close(channel);
- return sz;
+ return len;
}
static void chan_close(ssh_session session, ssh_channel channel,
void *userdata)
{
- int fd = *(int*) userdata;
+ ssh_userdata *sudata = (ssh_userdata *) userdata;
+ int fd = sudata->proto_read.fd;
(void) session;
(void) channel;