mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Passthrough for ssh commands to proxy
This commit is contained in:
parent
6172129f6f
commit
e26cb1aca4
@ -187,6 +187,7 @@ dist_tmate_slave_SOURCES = \
|
|||||||
tmate-slave.c \
|
tmate-slave.c \
|
||||||
tmate-ssh-client-pty.c \
|
tmate-ssh-client-pty.c \
|
||||||
tmate-ssh-daemon.c \
|
tmate-ssh-daemon.c \
|
||||||
|
tmate-ssh-exec.c \
|
||||||
tmate-ssh-server.c \
|
tmate-ssh-server.c \
|
||||||
tmux-bare.c \
|
tmux-bare.c \
|
||||||
tty-acs.c \
|
tty-acs.c \
|
||||||
|
1
client.c
1
client.c
@ -329,6 +329,7 @@ client_send_identify(int flags)
|
|||||||
sizeof(data.ip_address));
|
sizeof(data.ip_address));
|
||||||
strncpy(data.pubkey, tmate_session->ssh_client.pubkey,
|
strncpy(data.pubkey, tmate_session->ssh_client.pubkey,
|
||||||
sizeof(data.pubkey));
|
sizeof(data.pubkey));
|
||||||
|
data.readonly = tmate_session->readonly;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data.flags = flags;
|
data.flags = flags;
|
||||||
|
@ -1033,6 +1033,7 @@ server_client_msg_identify(
|
|||||||
#ifdef TMATE_SLAVE
|
#ifdef TMATE_SLAVE
|
||||||
c->ip_address = xstrdup(data->ip_address);
|
c->ip_address = xstrdup(data->ip_address);
|
||||||
c->pubkey = xstrdup(data->pubkey);
|
c->pubkey = xstrdup(data->pubkey);
|
||||||
|
c->readonly = data->readonly;
|
||||||
tmate_notify_client_join(tmate_session, c);
|
tmate_notify_client_join(tmate_session, c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,14 @@ void msgpack_pack_string(msgpack_packer *pk, const char *str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void msgpack_pack_boolean(msgpack_packer *pk, bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
msgpack_pack_true(pk);
|
||||||
|
else
|
||||||
|
msgpack_pack_false(pk);
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy/pasted from msgpack sources, except we include the v4 support */
|
/* Copy/pasted from msgpack sources, except we include the v4 support */
|
||||||
int _msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
|
int _msgpack_pack_object(msgpack_packer* pk, msgpack_object d)
|
||||||
{
|
{
|
||||||
@ -195,6 +203,24 @@ int64_t unpack_int(struct tmate_unpacker *uk)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool unpack_bool(struct tmate_unpacker *uk)
|
||||||
|
{
|
||||||
|
bool val;
|
||||||
|
|
||||||
|
if (uk->argc == 0)
|
||||||
|
tmate_decoder_error();
|
||||||
|
|
||||||
|
if (uk->argv[0].type != MSGPACK_OBJECT_BOOLEAN)
|
||||||
|
tmate_decoder_error();
|
||||||
|
|
||||||
|
val = uk->argv[0].via.boolean;
|
||||||
|
|
||||||
|
uk->argv++;
|
||||||
|
uk->argc--;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len)
|
void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len)
|
||||||
{
|
{
|
||||||
if (uk->argc == 0)
|
if (uk->argc == 0)
|
||||||
|
@ -10,6 +10,7 @@ enum tmate_control_out_msg_types {
|
|||||||
TMATE_CTL_SNAPSHOT,
|
TMATE_CTL_SNAPSHOT,
|
||||||
TMATE_CTL_CLIENT_JOIN,
|
TMATE_CTL_CLIENT_JOIN,
|
||||||
TMATE_CTL_CLIENT_LEFT,
|
TMATE_CTL_CLIENT_LEFT,
|
||||||
|
TMATE_CTL_EXEC,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -18,8 +19,9 @@ enum tmate_control_out_msg_types {
|
|||||||
[TMATE_CTL_DEAMON_OUT_MSG, object: msg]
|
[TMATE_CTL_DEAMON_OUT_MSG, object: msg]
|
||||||
[TMATE_CTL_SNAPSHOT, [[int: pane_id, [int: cur_x, int: cur_y], int: mode,
|
[TMATE_CTL_SNAPSHOT, [[int: pane_id, [int: cur_x, int: cur_y], int: mode,
|
||||||
[[string: line_utf8, [int: char_attr, ...]], ...], ...], ...]]
|
[[string: line_utf8, [int: char_attr, ...]], ...], ...], ...]]
|
||||||
[TMATE_CTL_CLIENT_JOIN, int: client_id, string: ip_address, string: pubkey]
|
[TMATE_CTL_CLIENT_JOIN, int: client_id, string: ip_address, string: pubkey, boolean: readonly]
|
||||||
[TMATE_CTL_CLIENT_LEFT, int: client_id]
|
[TMATE_CTL_CLIENT_LEFT, int: client_id]
|
||||||
|
[TMATE_CTL_EXEC, string: username, string: ip_address, string: pubkey, string: command]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum tmate_control_in_msg_types {
|
enum tmate_control_in_msg_types {
|
||||||
@ -27,6 +29,7 @@ enum tmate_control_in_msg_types {
|
|||||||
TMATE_CTL_REQUEST_SNAPSHOT,
|
TMATE_CTL_REQUEST_SNAPSHOT,
|
||||||
TMATE_CTL_PANE_KEYS,
|
TMATE_CTL_PANE_KEYS,
|
||||||
TMATE_CTL_RESIZE,
|
TMATE_CTL_RESIZE,
|
||||||
|
TMATE_CTL_EXEC_RESPONSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -34,6 +37,7 @@ enum tmate_control_in_msg_types {
|
|||||||
[TMATE_CTL_REQUEST_SNAPSHOT, int: max_history_lines]
|
[TMATE_CTL_REQUEST_SNAPSHOT, int: max_history_lines]
|
||||||
[TMATE_CTL_PANE_KEYS, int: pane_id, string: keys]
|
[TMATE_CTL_PANE_KEYS, int: pane_id, string: keys]
|
||||||
[TMATE_CTL_RESIZE, int: sx, int: sy] // sx == -1: no clients
|
[TMATE_CTL_RESIZE, int: sx, int: sy] // sx == -1: no clients
|
||||||
|
[TMATE_CTL_EXEC_RESPONSE, int: exit_code, string: message]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum tmate_daemon_out_msg_types {
|
enum tmate_daemon_out_msg_types {
|
||||||
|
111
tmate-proxy.c
111
tmate-proxy.c
@ -1,6 +1,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
#include "tmate-protocol.h"
|
#include "tmate-protocol.h"
|
||||||
@ -147,7 +148,20 @@ static void ctl_resize(struct tmate_session *session,
|
|||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_dispatch_proxy_message(struct tmate_session *session,
|
static void ctl_ssh_exec_response(struct tmate_session *session,
|
||||||
|
struct tmate_unpacker *uk)
|
||||||
|
{
|
||||||
|
int exit_code;
|
||||||
|
char *message;
|
||||||
|
|
||||||
|
exit_code = unpack_int(uk);
|
||||||
|
message = unpack_string(uk);
|
||||||
|
|
||||||
|
tmate_dump_exec_response(session, exit_code, message);
|
||||||
|
free(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tmate_dispatch_proxy_message(struct tmate_session *session,
|
||||||
struct tmate_unpacker *uk)
|
struct tmate_unpacker *uk)
|
||||||
{
|
{
|
||||||
int cmd = unpack_int(uk);
|
int cmd = unpack_int(uk);
|
||||||
@ -157,21 +171,38 @@ void tmate_dispatch_proxy_message(struct tmate_session *session,
|
|||||||
dispatch(TMATE_CTL_REQUEST_SNAPSHOT, ctl_daemon_request_snapshot);
|
dispatch(TMATE_CTL_REQUEST_SNAPSHOT, ctl_daemon_request_snapshot);
|
||||||
dispatch(TMATE_CTL_PANE_KEYS, ctl_pane_keys);
|
dispatch(TMATE_CTL_PANE_KEYS, ctl_pane_keys);
|
||||||
dispatch(TMATE_CTL_RESIZE, ctl_resize);
|
dispatch(TMATE_CTL_RESIZE, ctl_resize);
|
||||||
|
dispatch(TMATE_CTL_EXEC_RESPONSE, ctl_ssh_exec_response);
|
||||||
default: tmate_warn("Bad proxy message type: %d", cmd);
|
default: tmate_warn("Bad proxy message type: %d", cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tmate_proxy_exec(struct tmate_session *session, const char *command)
|
||||||
|
{
|
||||||
|
struct tmate_ssh_client *client = &session->ssh_client;
|
||||||
|
|
||||||
|
if (!tmate_has_proxy())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pack(array, 5);
|
||||||
|
pack(int, TMATE_CTL_EXEC);
|
||||||
|
pack(string, client->username);
|
||||||
|
pack(string, client->ip_address);
|
||||||
|
pack(string, client->pubkey);
|
||||||
|
pack(string, command);
|
||||||
|
}
|
||||||
|
|
||||||
void tmate_notify_client_join(struct tmate_session *session,
|
void tmate_notify_client_join(struct tmate_session *session,
|
||||||
struct client *c)
|
struct client *c)
|
||||||
{
|
{
|
||||||
if (!tmate_has_proxy())
|
if (!tmate_has_proxy())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pack(array, 4);
|
pack(array, 5);
|
||||||
pack(int, TMATE_CTL_CLIENT_JOIN);
|
pack(int, TMATE_CTL_CLIENT_JOIN);
|
||||||
pack(int, c->id);
|
pack(int, c->id);
|
||||||
pack(string, c->ip_address);
|
pack(string, c->ip_address);
|
||||||
pack(string, c->pubkey);
|
pack(string, c->pubkey);
|
||||||
|
pack(boolean, c->readonly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_notify_client_left(struct tmate_session *session,
|
void tmate_notify_client_left(struct tmate_session *session,
|
||||||
@ -216,13 +247,87 @@ void tmate_send_proxy_header(struct tmate_session *session)
|
|||||||
pack(string, session->session_token_ro);
|
pack(string, session->session_token_ro);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_init_proxy_session(struct tmate_session *session)
|
static void on_proxy_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = userdata;
|
||||||
|
tmate_dispatch_proxy_message(session, uk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_proxy_read(struct bufferevent *bev, void *_session)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = _session;
|
||||||
|
struct evbuffer *proxy_in;
|
||||||
|
ssize_t written;
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
proxy_in = bufferevent_get_input(session->bev_proxy);
|
||||||
|
|
||||||
|
while (evbuffer_get_length(proxy_in)) {
|
||||||
|
tmate_decoder_get_buffer(&session->proxy_decoder, &buf, &len);
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
tmate_fatal("No more room in client decoder. Message too big?");
|
||||||
|
|
||||||
|
written = evbuffer_remove(proxy_in, buf, len);
|
||||||
|
if (written < 0)
|
||||||
|
tmate_fatal("Cannot read proxy buffer");
|
||||||
|
|
||||||
|
tmate_decoder_commit(&session->proxy_decoder, written);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_proxy_encoder_write(void *userdata, struct evbuffer *buffer)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = userdata;
|
||||||
|
struct evbuffer *proxy_out;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
proxy_out = bufferevent_get_output(session->bev_proxy);
|
||||||
|
|
||||||
|
if (evbuffer_add_buffer(proxy_out, buffer) < 0)
|
||||||
|
tmate_fatal("Cannot write to proxy buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_proxy_event_default(struct tmate_session *session, short events)
|
||||||
|
{
|
||||||
|
if (events & BEV_EVENT_EOF)
|
||||||
|
tmate_fatal("Connection to proxy closed");
|
||||||
|
|
||||||
|
if (events & BEV_EVENT_ERROR)
|
||||||
|
tmate_fatal("Connection to proxy error: %s",
|
||||||
|
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_proxy_event(struct bufferevent *bev, short events, void *_session)
|
||||||
|
{
|
||||||
|
struct tmate_session *session = _session;
|
||||||
|
session->on_proxy_error(session, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_init_proxy(struct tmate_session *session,
|
||||||
|
on_proxy_error_cb on_proxy_error)
|
||||||
{
|
{
|
||||||
if (!tmate_has_proxy())
|
if (!tmate_has_proxy())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
session->proxy_sx = -1;
|
session->proxy_sx = -1;
|
||||||
session->proxy_sy = -1;
|
session->proxy_sy = -1;
|
||||||
|
|
||||||
|
/* session->proxy_fd is already connected */
|
||||||
|
session->bev_proxy = bufferevent_socket_new(ev_base, session->proxy_fd,
|
||||||
|
BEV_OPT_CLOSE_ON_FREE);
|
||||||
|
if (!session->bev_proxy)
|
||||||
|
tmate_fatal("Cannot setup socket bufferevent");
|
||||||
|
|
||||||
|
session->on_proxy_error = on_proxy_error ?: on_proxy_event_default;
|
||||||
|
|
||||||
|
bufferevent_setcb(session->bev_proxy,
|
||||||
|
on_proxy_read, NULL, on_proxy_event, session);
|
||||||
|
bufferevent_enable(session->bev_proxy, EV_READ | EV_WRITE);
|
||||||
|
|
||||||
|
tmate_encoder_init(&session->proxy_encoder, on_proxy_encoder_write, session);
|
||||||
|
tmate_decoder_init(&session->proxy_decoder, on_proxy_decoder_read, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tmate_connect_to_proxy(const char *hostname, int port)
|
static int _tmate_connect_to_proxy(const char *hostname, int port)
|
||||||
|
@ -434,10 +434,26 @@ static void tmate_spawn_slave_pty_client(struct tmate_session *session)
|
|||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tmate_spawn_slave_exec(struct tmate_session *session)
|
||||||
|
{
|
||||||
|
close_fds_except((int[]){ssh_get_fd(session->ssh_client.session),
|
||||||
|
log_file ? fileno(log_file) : -1,
|
||||||
|
session->proxy_fd}, 3);
|
||||||
|
jail();
|
||||||
|
event_reinit(ev_base);
|
||||||
|
|
||||||
|
tmate_client_exec_init(session);
|
||||||
|
|
||||||
|
if (event_base_dispatch(ev_base) < 0)
|
||||||
|
tmate_fatal("Cannot run event loop");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
void tmate_spawn_slave(struct tmate_session *session)
|
void tmate_spawn_slave(struct tmate_session *session)
|
||||||
{
|
{
|
||||||
switch (session->ssh_client.role) {
|
switch (session->ssh_client.role) {
|
||||||
case TMATE_ROLE_DAEMON: tmate_spawn_slave_daemon(session); break;
|
case TMATE_ROLE_DAEMON: tmate_spawn_slave_daemon(session); break;
|
||||||
case TMATE_ROLE_PTY_CLIENT: tmate_spawn_slave_pty_client(session); break;
|
case TMATE_ROLE_PTY_CLIENT: tmate_spawn_slave_pty_client(session); break;
|
||||||
|
case TMATE_ROLE_EXEC: tmate_spawn_slave_exec(session); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,58 +1,6 @@
|
|||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
static void on_proxy_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
|
||||||
{
|
|
||||||
struct tmate_session *session = userdata;
|
|
||||||
tmate_dispatch_proxy_message(session, uk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_proxy_read(struct bufferevent *bev, void *_session)
|
|
||||||
{
|
|
||||||
struct tmate_session *session = _session;
|
|
||||||
struct evbuffer *proxy_in;
|
|
||||||
ssize_t written;
|
|
||||||
char *buf;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
proxy_in = bufferevent_get_input(session->bev_proxy);
|
|
||||||
|
|
||||||
while (evbuffer_get_length(proxy_in)) {
|
|
||||||
tmate_decoder_get_buffer(&session->proxy_decoder, &buf, &len);
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
tmate_fatal("No more room in client decoder. Message too big?");
|
|
||||||
|
|
||||||
written = evbuffer_remove(proxy_in, buf, len);
|
|
||||||
if (written < 0)
|
|
||||||
tmate_fatal("Cannot read proxy buffer");
|
|
||||||
|
|
||||||
tmate_decoder_commit(&session->proxy_decoder, written);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_proxy_encoder_write(void *userdata, struct evbuffer *buffer)
|
|
||||||
{
|
|
||||||
struct tmate_session *session = userdata;
|
|
||||||
struct evbuffer *proxy_out;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
proxy_out = bufferevent_get_output(session->bev_proxy);
|
|
||||||
|
|
||||||
if (evbuffer_add_buffer(proxy_out, buffer) < 0)
|
|
||||||
tmate_fatal("Cannot write to proxy buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_proxy_event(struct bufferevent *bev, short events, void *_session)
|
|
||||||
{
|
|
||||||
if (events & BEV_EVENT_EOF)
|
|
||||||
tmate_fatal("Connection to proxy closed");
|
|
||||||
|
|
||||||
if (events & BEV_EVENT_ERROR)
|
|
||||||
tmate_fatal("Connection to proxy error: %s",
|
|
||||||
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void on_daemon_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
static void on_daemon_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
||||||
{
|
{
|
||||||
struct tmate_session *session = userdata;
|
struct tmate_session *session = userdata;
|
||||||
@ -117,25 +65,6 @@ static void on_daemon_encoder_write(void *userdata, struct evbuffer *buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_proxy(struct tmate_session *session)
|
|
||||||
{
|
|
||||||
/* session->proxy_fd is already connected */
|
|
||||||
session->bev_proxy = bufferevent_socket_new(ev_base, session->proxy_fd,
|
|
||||||
BEV_OPT_CLOSE_ON_FREE);
|
|
||||||
if (!session->bev_proxy)
|
|
||||||
tmate_fatal("Cannot setup socket bufferevent");
|
|
||||||
|
|
||||||
bufferevent_setcb(session->bev_proxy,
|
|
||||||
on_proxy_read, NULL, on_proxy_event, session);
|
|
||||||
bufferevent_enable(session->bev_proxy, EV_READ | EV_WRITE);
|
|
||||||
|
|
||||||
tmate_encoder_init(&session->proxy_encoder, on_proxy_encoder_write, session);
|
|
||||||
tmate_decoder_init(&session->proxy_decoder, on_proxy_decoder_read, session);
|
|
||||||
|
|
||||||
tmate_init_proxy_session(session);
|
|
||||||
tmate_send_proxy_header(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tmate_daemon_init(struct tmate_session *session)
|
void tmate_daemon_init(struct tmate_session *session)
|
||||||
{
|
{
|
||||||
struct tmate_ssh_client *client = &session->ssh_client;
|
struct tmate_ssh_client *client = &session->ssh_client;
|
||||||
@ -149,6 +78,6 @@ void tmate_daemon_init(struct tmate_session *session)
|
|||||||
tmate_encoder_init(&session->daemon_encoder, on_daemon_encoder_write, session);
|
tmate_encoder_init(&session->daemon_encoder, on_daemon_encoder_write, session);
|
||||||
tmate_decoder_init(&session->daemon_decoder, on_daemon_decoder_read, session);
|
tmate_decoder_init(&session->daemon_decoder, on_daemon_decoder_read, session);
|
||||||
|
|
||||||
if (tmate_has_proxy())
|
tmate_init_proxy(session, NULL);
|
||||||
init_proxy(session);
|
tmate_send_proxy_header(session);
|
||||||
}
|
}
|
||||||
|
37
tmate-ssh-exec.c
Normal file
37
tmate-ssh-exec.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "tmate.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libssh/server.h>
|
||||||
|
|
||||||
|
void tmate_dump_exec_response(struct tmate_session *session,
|
||||||
|
int exit_code, const char *message)
|
||||||
|
{
|
||||||
|
struct tmate_ssh_client *client = &session->ssh_client;
|
||||||
|
|
||||||
|
ssh_channel_write(client->channel, message, strlen(message));
|
||||||
|
ssh_channel_request_send_exit_status(client->channel, exit_code);
|
||||||
|
|
||||||
|
ssh_channel_send_eof(client->channel);
|
||||||
|
ssh_channel_close(client->channel);
|
||||||
|
|
||||||
|
if (event_base_loopexit(ev_base, NULL) < 0)
|
||||||
|
tmate_fatal("cannot stop event loop");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_proxy_error(struct tmate_session *session, short events)
|
||||||
|
{
|
||||||
|
tmate_warn("Lost proxy connection");
|
||||||
|
tmate_dump_exec_response(session, 1, "Internal Error\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void tmate_client_exec_init(struct tmate_session *session)
|
||||||
|
{
|
||||||
|
struct tmate_ssh_client *client = &session->ssh_client;
|
||||||
|
|
||||||
|
memset(&client->channel_cb, 0, sizeof(client->channel_cb));
|
||||||
|
ssh_callbacks_init(&client->channel_cb);
|
||||||
|
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
||||||
|
|
||||||
|
tmate_init_proxy(session, on_proxy_error);
|
||||||
|
|
||||||
|
tmate_proxy_exec(session, client->exec_command);
|
||||||
|
}
|
@ -45,6 +45,9 @@ static int shell_request(ssh_session session, ssh_channel channel,
|
|||||||
{
|
{
|
||||||
struct tmate_ssh_client *client = userdata;
|
struct tmate_ssh_client *client = userdata;
|
||||||
|
|
||||||
|
if (client->role)
|
||||||
|
return 1;
|
||||||
|
|
||||||
client->role = TMATE_ROLE_PTY_CLIENT;
|
client->role = TMATE_ROLE_PTY_CLIENT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -55,12 +58,32 @@ static int subsystem_request(ssh_session session, ssh_channel channel,
|
|||||||
{
|
{
|
||||||
struct tmate_ssh_client *client = userdata;
|
struct tmate_ssh_client *client = userdata;
|
||||||
|
|
||||||
|
if (client->role)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (!strcmp(subsystem, "tmate"))
|
if (!strcmp(subsystem, "tmate"))
|
||||||
client->role = TMATE_ROLE_DAEMON;
|
client->role = TMATE_ROLE_DAEMON;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int exec_request(ssh_session session, ssh_channel channel,
|
||||||
|
const char *command, void *userdata)
|
||||||
|
{
|
||||||
|
struct tmate_ssh_client *client = userdata;
|
||||||
|
|
||||||
|
if (client->role)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!tmate_has_proxy())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
client->role = TMATE_ROLE_EXEC;
|
||||||
|
client->exec_command = xstrdup(command);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
|
static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
|
||||||
{
|
{
|
||||||
struct tmate_ssh_client *client = userdata;
|
struct tmate_ssh_client *client = userdata;
|
||||||
@ -82,9 +105,10 @@ static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
|
|||||||
memset(&client->channel_cb, 0, sizeof(client->channel_cb));
|
memset(&client->channel_cb, 0, sizeof(client->channel_cb));
|
||||||
ssh_callbacks_init(&client->channel_cb);
|
ssh_callbacks_init(&client->channel_cb);
|
||||||
client->channel_cb.userdata = client;
|
client->channel_cb.userdata = client;
|
||||||
client->channel_cb.channel_pty_request_function = pty_request,
|
client->channel_cb.channel_pty_request_function = pty_request;
|
||||||
client->channel_cb.channel_shell_request_function = shell_request,
|
client->channel_cb.channel_shell_request_function = shell_request;
|
||||||
client->channel_cb.channel_subsystem_request_function = subsystem_request,
|
client->channel_cb.channel_subsystem_request_function = subsystem_request;
|
||||||
|
client->channel_cb.channel_exec_request_function = exec_request;
|
||||||
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
||||||
|
|
||||||
return client->channel;
|
return client->channel;
|
||||||
|
35
tmate.h
35
tmate.h
@ -46,6 +46,7 @@ extern void tmate_encoder_init(struct tmate_encoder *encoder,
|
|||||||
|
|
||||||
/* These functions deal with dual v4/v5 support through mpac_version */
|
/* These functions deal with dual v4/v5 support through mpac_version */
|
||||||
extern void msgpack_pack_string(msgpack_packer *pk, const char *str);
|
extern void msgpack_pack_string(msgpack_packer *pk, const char *str);
|
||||||
|
extern void msgpack_pack_boolean(msgpack_packer *pk, bool value);
|
||||||
extern int _msgpack_pack_object(msgpack_packer *pk, msgpack_object d);
|
extern int _msgpack_pack_object(msgpack_packer *pk, msgpack_object d);
|
||||||
#define msgpack_pack_object _msgpack_pack_object
|
#define msgpack_pack_object _msgpack_pack_object
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ struct tmate_unpacker {
|
|||||||
extern void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj);
|
extern void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj);
|
||||||
extern void tmate_decoder_error(void);
|
extern void tmate_decoder_error(void);
|
||||||
extern int64_t unpack_int(struct tmate_unpacker *uk);
|
extern int64_t unpack_int(struct tmate_unpacker *uk);
|
||||||
|
extern bool unpack_bool(struct tmate_unpacker *uk);
|
||||||
extern void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len);
|
extern void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len);
|
||||||
extern char *unpack_string(struct tmate_unpacker *uk);
|
extern char *unpack_string(struct tmate_unpacker *uk);
|
||||||
extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested);
|
extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested);
|
||||||
@ -88,8 +90,6 @@ extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *neste
|
|||||||
|
|
||||||
extern void printflike1 tmate_notify(const char *fmt, ...);
|
extern void printflike1 tmate_notify(const char *fmt, ...);
|
||||||
extern void printflike2 tmate_notify_later(int timeout, const char *fmt, ...);
|
extern void printflike2 tmate_notify_later(int timeout, const char *fmt, ...);
|
||||||
extern void tmate_notify_client_join(struct tmate_session *s, struct client *c);
|
|
||||||
extern void tmate_notify_client_left(struct tmate_session *s, struct client *c);
|
|
||||||
|
|
||||||
extern void tmate_client_resize(u_int sx, u_int sy);
|
extern void tmate_client_resize(u_int sx, u_int sy);
|
||||||
extern void tmate_client_pane_key(int pane_id, int key);
|
extern void tmate_client_pane_key(int pane_id, int key);
|
||||||
@ -109,13 +109,19 @@ extern char *tmate_left_status, *tmate_right_status;
|
|||||||
extern void tmate_dispatch_daemon_message(struct tmate_session *session,
|
extern void tmate_dispatch_daemon_message(struct tmate_session *session,
|
||||||
struct tmate_unpacker *uk);
|
struct tmate_unpacker *uk);
|
||||||
|
|
||||||
/* tmate-ssh-client.c */
|
/* tmate-ssh-daemon.c */
|
||||||
|
|
||||||
#define TMATE_KEYFRAME_INTERVAL_SEC 10
|
#define TMATE_KEYFRAME_INTERVAL_SEC 10
|
||||||
#define TMATE_KEYFRAME_MAX_SIZE 1024*1024
|
#define TMATE_KEYFRAME_MAX_SIZE 1024*1024
|
||||||
|
|
||||||
extern void tmate_daemon_init(struct tmate_session *session);
|
extern void tmate_daemon_init(struct tmate_session *session);
|
||||||
|
|
||||||
|
/* tmate-ssh-exec.c */
|
||||||
|
|
||||||
|
extern void tmate_dump_exec_response(struct tmate_session *session,
|
||||||
|
int exit_code, const char *message);
|
||||||
|
extern void tmate_client_exec_init(struct tmate_session *session);
|
||||||
|
|
||||||
/* tmate-ssh-client-pty.c */
|
/* tmate-ssh-client-pty.c */
|
||||||
|
|
||||||
extern void tmate_client_pty_init(struct tmate_session *session);
|
extern void tmate_client_pty_init(struct tmate_session *session);
|
||||||
@ -128,6 +134,7 @@ extern void tmate_flush_pty(struct tmate_session *session);
|
|||||||
|
|
||||||
#define TMATE_ROLE_DAEMON 1
|
#define TMATE_ROLE_DAEMON 1
|
||||||
#define TMATE_ROLE_PTY_CLIENT 2
|
#define TMATE_ROLE_PTY_CLIENT 2
|
||||||
|
#define TMATE_ROLE_EXEC 3
|
||||||
|
|
||||||
struct tmate_ssh_client {
|
struct tmate_ssh_client {
|
||||||
char ip_address[64];
|
char ip_address[64];
|
||||||
@ -145,6 +152,8 @@ struct tmate_ssh_client {
|
|||||||
char *username;
|
char *username;
|
||||||
char *pubkey;
|
char *pubkey;
|
||||||
|
|
||||||
|
char *exec_command;
|
||||||
|
|
||||||
struct winsize winsize_pty;
|
struct winsize winsize_pty;
|
||||||
|
|
||||||
struct event ev_ssh;
|
struct event ev_ssh;
|
||||||
@ -183,11 +192,13 @@ struct tmate_settings {
|
|||||||
};
|
};
|
||||||
extern struct tmate_settings *tmate_settings;
|
extern struct tmate_settings *tmate_settings;
|
||||||
|
|
||||||
|
typedef void on_proxy_error_cb(struct tmate_session *session, short events);
|
||||||
|
|
||||||
struct tmate_session {
|
struct tmate_session {
|
||||||
struct tmate_ssh_client ssh_client;
|
struct tmate_ssh_client ssh_client;
|
||||||
int tmux_socket_fd;
|
int tmux_socket_fd;
|
||||||
|
|
||||||
/* only for deamon */
|
/* only for role deamon */
|
||||||
const char *session_token;
|
const char *session_token;
|
||||||
const char *session_token_ro;
|
const char *session_token_ro;
|
||||||
|
|
||||||
@ -201,11 +212,17 @@ struct tmate_session {
|
|||||||
struct tmate_encoder proxy_encoder;
|
struct tmate_encoder proxy_encoder;
|
||||||
struct tmate_decoder proxy_decoder;
|
struct tmate_decoder proxy_decoder;
|
||||||
u_int proxy_sx, proxy_sy;
|
u_int proxy_sx, proxy_sy;
|
||||||
|
on_proxy_error_cb *on_proxy_error;
|
||||||
|
|
||||||
/* only for client-pty */
|
/* only for role client-pty */
|
||||||
int pty;
|
int pty;
|
||||||
struct event ev_pty;
|
struct event ev_pty;
|
||||||
bool readonly;
|
bool readonly;
|
||||||
|
|
||||||
|
/* only for role-exec */
|
||||||
|
bool response_received;
|
||||||
|
bool response_status;
|
||||||
|
const char *response_message;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct tmate_session *tmate_session;
|
extern struct tmate_session *tmate_session;
|
||||||
@ -216,13 +233,15 @@ extern void tmate_spawn_slave(struct tmate_session *session);
|
|||||||
|
|
||||||
/* tmate-proxy.c */
|
/* tmate-proxy.c */
|
||||||
|
|
||||||
extern void tmate_dispatch_proxy_message(struct tmate_session *session,
|
extern void tmate_proxy_exec(struct tmate_session *session, const char *command);
|
||||||
struct tmate_unpacker *uk);
|
extern void tmate_notify_client_join(struct tmate_session *s, struct client *c);
|
||||||
|
extern void tmate_notify_client_left(struct tmate_session *s, struct client *c);
|
||||||
|
|
||||||
extern void tmate_send_proxy_daemon_msg(struct tmate_session *session,
|
extern void tmate_send_proxy_daemon_msg(struct tmate_session *session,
|
||||||
struct tmate_unpacker *uk);
|
struct tmate_unpacker *uk);
|
||||||
extern void tmate_send_proxy_header(struct tmate_session *session);
|
extern void tmate_send_proxy_header(struct tmate_session *session);
|
||||||
extern void tmate_init_proxy_session(struct tmate_session *session);
|
extern void tmate_init_proxy(struct tmate_session *session,
|
||||||
|
on_proxy_error_cb on_proxy_error);
|
||||||
|
|
||||||
extern int tmate_connect_to_proxy(void);
|
extern int tmate_connect_to_proxy(void);
|
||||||
static inline bool tmate_has_proxy(void)
|
static inline bool tmate_has_proxy(void)
|
||||||
|
2
tmux.h
2
tmux.h
@ -480,6 +480,7 @@ struct msg_identify_data {
|
|||||||
#ifdef TMATE_SLAVE
|
#ifdef TMATE_SLAVE
|
||||||
char ip_address[64];
|
char ip_address[64];
|
||||||
char pubkey[2048]; /* hopefully enough :) */
|
char pubkey[2048]; /* hopefully enough :) */
|
||||||
|
int readonly;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IDENTIFY_UTF8 0x1
|
#define IDENTIFY_UTF8 0x1
|
||||||
@ -1389,6 +1390,7 @@ struct client {
|
|||||||
#ifdef TMATE_SLAVE
|
#ifdef TMATE_SLAVE
|
||||||
char *ip_address;
|
char *ip_address;
|
||||||
char *pubkey;
|
char *pubkey;
|
||||||
|
int readonly;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
ARRAY_DECL(clients, struct client *);
|
ARRAY_DECL(clients, struct client *);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user