diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-07-27 17:08:02 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-07-27 17:08:02 +0200 |
commit | 48f11c634b04d6960404ba18240d33f6cc2d38aa (patch) | |
tree | 07756d7f87069e6d9065e737a3ac4a959b88aede | |
parent | 4c31056b7bc7c5fbcf81bff0fdeb2229b4f8f0ad (diff) |
jail protocol handshake read/writefeature/jail_protocol
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | src/jail_protocol.c | 68 | ||||
-rw-r--r-- | src/jail_protocol.h | 7 | ||||
-rw-r--r-- | src/protocol_ssh.c | 20 |
3 files changed, 72 insertions, 23 deletions
diff --git a/src/jail_protocol.c b/src/jail_protocol.c index 582f298..7112354 100644 --- a/src/jail_protocol.c +++ b/src/jail_protocol.c @@ -62,8 +62,8 @@ ssize_t jail_protocol_readhdr(jail_data *dst, unsigned char *buf, hdr = (jail_protocol_hdr *) buf; if (ntohl(hdr->magic) != PROTO_MAGIC) return -1; - data_siz = bufsiz - sizeof(*hdr); - if (ntohl(hdr->size) != data_siz) + data_siz = ntohl(hdr->size); + if (data_siz > bufsiz - sizeof(*hdr)) return -1; dst->last_type = ntohl(hdr->type); @@ -84,7 +84,7 @@ ssize_t jail_protocol_readhdr(jail_data *dst, unsigned char *buf, break; } - return data_siz; + return data_siz + sizeof(*hdr); } ssize_t jail_protocol_writehdr(int type, unsigned char *buf, size_t bufsiz) @@ -100,7 +100,7 @@ ssize_t jail_protocol_writehdr(int type, unsigned char *buf, size_t bufsiz) hdr->magic = htonl(PROTO_MAGIC); hdr->type = htonl(type); data_siz = bufsiz - sizeof(*hdr); - hdr->size = data_siz; + hdr->size = htonl(data_siz); return data_siz; } @@ -112,6 +112,7 @@ handshake_read_loop(event_ctx *ev_ctx, int src_fd, void *user_data) int dst_fd = -1; ssize_t siz, rc = -1; unsigned char buf[BUFSIZ] = {0}; + off_t buf_off = 0; (void) ev_ctx; @@ -126,17 +127,32 @@ handshake_read_loop(event_ctx *ev_ctx, int src_fd, void *user_data) goto error; if (src_fd == ev_jail->sock_fd) { - rc = jail_protocol_readhdr(ev_jail->data, buf, siz); - - if (rc <= 0) - ev_ctx->active = 0; - if (rc > 0 && ev_jail->data->last_type == PROTO_TYPE_DATA) { - ev_jail->data->used = 1; - ev_ctx->active = 0; + while (1) { + rc = jail_protocol_readhdr(ev_jail->data, buf + buf_off, + siz - buf_off); + + if (rc < 0) { + ev_ctx->active = 0; + break; + } else { + ev_jail->data->used = 1; + if (ev_jail->data->last_type == PROTO_TYPE_DATA) { + ev_ctx->active = 0; + break; + } + } + + buf_off += rc; } } - return write(dst_fd, buf, siz) == siz; + if (buf_off < siz) { + rc = write(dst_fd, buf + buf_off, siz - buf_off); + if (rc != siz - buf_off) + goto error; + } + + return 1; error: ev_ctx->active = 0; return 1; @@ -146,12 +162,34 @@ int jail_protocol_handshake_read(event_ctx *ev_client, int client_fd, int tty_fd, jail_data *dst) { jail_event ev_jail = {0,0,0}; - int rc; ev_jail.data = dst; ev_jail.sock_fd = client_fd; ev_jail.tty_fd = tty_fd; - rc = event_loop(ev_client, handshake_read_loop, &ev_jail); + event_loop(ev_client, handshake_read_loop, &ev_jail); + + return !dst->used; +} + +int jail_protocol_handshake_write(int server_fd, jail_data *dst) +{ + ssize_t rc; + unsigned char buf[BUFSIZ] = {0}; + size_t min_siz; + + min_siz = MIN(strnlen(dst->user, USER_LEN), USER_LEN); + memcpy((char *) buf + sizeof(jail_protocol_hdr), dst->user, min_siz); + rc = jail_protocol_writehdr(PROTO_TYPE_USER, buf, sizeof(jail_protocol_hdr) + min_siz); + if (rc < 0) + return -1; + rc = write(server_fd, buf, sizeof(jail_protocol_hdr) + rc); + + min_siz = MIN(strnlen(dst->pass, PASS_LEN), PASS_LEN); + memcpy((char *) buf + sizeof(jail_protocol_hdr), dst->pass, min_siz); + rc = jail_protocol_writehdr(PROTO_TYPE_PASS, buf, sizeof(jail_protocol_hdr) + min_siz); + if (rc < 0) + return -1; + rc = write(server_fd, buf, sizeof(jail_protocol_hdr) + rc); - return rc || !ev_client->active; + return 0; } diff --git a/src/jail_protocol.h b/src/jail_protocol.h index 51cdf54..b608253 100644 --- a/src/jail_protocol.h +++ b/src/jail_protocol.h @@ -16,14 +16,14 @@ #define PROTO_TYPE_PASS 0x42424242 #define PROTO_TYPE_DATA 0x43434343 -typedef struct __attribute__((packed, aligned(4))) jail_data { +typedef struct jail_data { int used; uint32_t last_type; char user[USER_LEN+1]; char pass[PASS_LEN+1]; } jail_data; -typedef struct jail_protocol_hdr { +typedef struct __attribute__((packed, aligned(4))) jail_protocol_hdr { uint32_t magic; uint32_t type; uint32_t size; @@ -38,8 +38,7 @@ ssize_t jail_protocol_writehdr(int type, unsigned char *buf, size_t bufsiz); int jail_protocol_handshake_read(event_ctx *ev_client, int client_fd, int tty_fd, jail_data *dst); -int jail_protocol_handshake_write(event_ctx *ev_server, int server_fd, - int proto_fd, jail_data *dst); +int jail_protocol_handshake_write(int server_fd, jail_data *dst); int jail_protocol_loop(event_ctx *ctx, on_event_cb on_event, void *user_data); diff --git a/src/protocol_ssh.c b/src/protocol_ssh.c index cc490b2..ceddb0e 100644 --- a/src/protocol_ssh.c +++ b/src/protocol_ssh.c @@ -82,6 +82,7 @@ typedef struct ssh_data { typedef struct ssh_client { ssh_channel chan; + jail_data jail; forward_ctx dst; } ssh_client; @@ -106,7 +107,8 @@ 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_data *jail); static int auth_password(const char *user, const char *pass, ssh_login_cache *cache); static int client_mainloop(ssh_client *arg); @@ -486,7 +488,7 @@ static void ssh_mainloop(ssh_data *arg) } /* proceed to authentication */ - auth = authenticate(ses, cache); + auth = authenticate(ses, cache, &data.jail); if (!auth) { W("SSH authentication error: %s", ssh_get_error(ses)); goto failed; @@ -565,7 +567,8 @@ failed: } } -static int authenticate(ssh_session session, ssh_login_cache *cache) +static int authenticate(ssh_session session, ssh_login_cache *cache, + jail_data *jail) { ssh_message message; @@ -582,6 +585,10 @@ static int authenticate(ssh_session session, ssh_login_cache *cache) N("SSH: user '%s' wants to auth with pass '%s'", ssh_message_auth_user(message), ssh_message_auth_password(message)); + strncpy(jail->user, ssh_message_auth_user(message), + USER_LEN); + strncpy(jail->pass, ssh_message_auth_password(message), + PASS_LEN); if (auth_password(ssh_message_auth_user(message), ssh_message_auth_password(message), cache)) { @@ -710,7 +717,12 @@ static int client_mainloop(ssh_client *data) ssh_channel_close(chan); return 1; } - // JAIL PROTOCOL + if (jail_protocol_handshake_write(ctx->sock.fd, &data->jail)) { + E_STRERR("Jail protocol handshake to %s:%s", + ctx->host_buf, ctx->service_buf); + ssh_channel_close(chan); + return 1; + } ssh_channel_cb.userdata = &ctx->sock.fd; ssh_callbacks_init(&ssh_channel_cb); |