mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Refactored tmate
This commit is contained in:
parent
31cc091823
commit
4ac1183848
@ -179,8 +179,9 @@ dist_tmate_slave_SOURCES = \
|
||||
signal.c \
|
||||
status.c \
|
||||
tmate-debug.c \
|
||||
tmate-decoder.c \
|
||||
tmate-encoder.c \
|
||||
tmate-client-decoder.c \
|
||||
tmate-client-encoder.c \
|
||||
tmate-msgpack.c \
|
||||
tmate-slave.c \
|
||||
tmate-ssh-client-pty.c \
|
||||
tmate-ssh-client.c \
|
||||
|
4
client.c
4
client.c
@ -207,7 +207,7 @@ client_main(int argc, char **argv, int flags)
|
||||
}
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
fd = tmux_socket_fd;
|
||||
fd = tmate_session->tmux_socket_fd;
|
||||
#else
|
||||
|
||||
/*
|
||||
@ -325,7 +325,7 @@ client_send_identify(int flags)
|
||||
int fd;
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
strcpy(data.ip_address, tmate_client.ip_address);
|
||||
strcpy(data.ip_address, tmate_session->ssh_client.ip_address);
|
||||
#endif
|
||||
|
||||
data.flags = flags;
|
||||
|
6
log.c
6
log.c
@ -73,11 +73,13 @@ log_vwrite(int level, const char *msg, va_list ap)
|
||||
{
|
||||
char *fmt = NULL;
|
||||
|
||||
const char *token = tmate_session->session_token;
|
||||
|
||||
if (log_settings.log_level < level)
|
||||
return;
|
||||
|
||||
if (tmate_session_token) {
|
||||
if (asprintf(&fmt, "[%s] %s", tmate_session_token, msg) < 0)
|
||||
if (token) {
|
||||
if (asprintf(&fmt, "[%s] %s", token, msg) < 0)
|
||||
exit(1);
|
||||
msg = fmt;
|
||||
}
|
||||
|
2
server.c
2
server.c
@ -162,7 +162,7 @@ server_start(int lockfd, char *lockfile)
|
||||
#endif
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
server_fd = tmux_socket_fd;
|
||||
server_fd = tmate_session->tmux_socket_fd;
|
||||
#else
|
||||
server_fd = server_create_socket();
|
||||
server_client_create(pair[1]);
|
||||
|
@ -6,111 +6,21 @@ char *tmate_left_status, *tmate_right_status;
|
||||
|
||||
static struct session *main_session;
|
||||
|
||||
struct tmate_unpacker {
|
||||
msgpack_object *argv;
|
||||
int argc;
|
||||
};
|
||||
|
||||
static void decoder_error(void)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
tmate_print_trace();
|
||||
#endif
|
||||
tmate_fatal("Received a bad message");
|
||||
}
|
||||
|
||||
static void init_unpacker(struct tmate_unpacker *uk,
|
||||
msgpack_object obj)
|
||||
{
|
||||
if (obj.type != MSGPACK_OBJECT_ARRAY)
|
||||
decoder_error();
|
||||
|
||||
uk->argv = obj.via.array.ptr;
|
||||
uk->argc = obj.via.array.size;
|
||||
}
|
||||
|
||||
static int64_t unpack_int(struct tmate_unpacker *uk)
|
||||
{
|
||||
int64_t val;
|
||||
|
||||
if (uk->argc == 0)
|
||||
decoder_error();
|
||||
|
||||
if (uk->argv[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER &&
|
||||
uk->argv[0].type != MSGPACK_OBJECT_NEGATIVE_INTEGER)
|
||||
decoder_error();
|
||||
|
||||
val = uk->argv[0].via.i64;
|
||||
|
||||
uk->argv++;
|
||||
uk->argc--;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void unpack_raw(struct tmate_unpacker *uk,
|
||||
const char **buf, size_t *len)
|
||||
{
|
||||
if (uk->argc == 0)
|
||||
decoder_error();
|
||||
|
||||
if (uk->argv[0].type != MSGPACK_OBJECT_RAW)
|
||||
decoder_error();
|
||||
|
||||
*len = uk->argv[0].via.raw.size;
|
||||
*buf = uk->argv[0].via.raw.ptr;
|
||||
|
||||
uk->argv++;
|
||||
uk->argc--;
|
||||
}
|
||||
|
||||
static char *unpack_string(struct tmate_unpacker *uk)
|
||||
{
|
||||
const char *buf;
|
||||
char *alloc_buf;
|
||||
size_t len;
|
||||
|
||||
unpack_raw(uk, &buf, &len);
|
||||
|
||||
alloc_buf = xmalloc(len + 1);
|
||||
memcpy(alloc_buf, buf, len);
|
||||
alloc_buf[len] = '\0';
|
||||
|
||||
return alloc_buf;
|
||||
}
|
||||
|
||||
static void unpack_array(struct tmate_unpacker *uk,
|
||||
struct tmate_unpacker *nested)
|
||||
{
|
||||
if (uk->argc == 0)
|
||||
decoder_error();
|
||||
|
||||
init_unpacker(nested, uk->argv[0]);
|
||||
|
||||
uk->argv++;
|
||||
uk->argc--;
|
||||
}
|
||||
|
||||
#define unpack_each(nested_uk, tmp_uk, uk) \
|
||||
for (unpack_array(uk, tmp_uk); \
|
||||
(tmp_uk)->argc > 0 && (init_unpacker(nested_uk, (tmp_uk)->argv[0]), 1); \
|
||||
(tmp_uk)->argv++, (tmp_uk)->argc--)
|
||||
|
||||
static void tmate_header(struct tmate_decoder *decoder,
|
||||
static void tmate_header(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
char port_arg[16] = {0};
|
||||
char *client_version = xstrdup("< 1.8.6");
|
||||
char tmp[512];
|
||||
|
||||
decoder->protocol = unpack_int(uk);
|
||||
if (decoder->protocol >= 3) {
|
||||
session->client_protocol_version = unpack_int(uk);
|
||||
if (session->client_protocol_version >= 3) {
|
||||
free(client_version);
|
||||
client_version = unpack_string(uk);
|
||||
}
|
||||
|
||||
tmate_debug("new master, client version: %s, protocol version: %d",
|
||||
client_version, decoder->protocol);
|
||||
client_version, session->client_protocol_version);
|
||||
|
||||
#if 0
|
||||
if (strcmp(client_version, TMATE_LATEST_VERSION))
|
||||
@ -119,14 +29,14 @@ static void tmate_header(struct tmate_decoder *decoder,
|
||||
|
||||
free(client_version);
|
||||
|
||||
if (tmate_settings.ssh_port != 22)
|
||||
sprintf(port_arg, " -p%d", tmate_settings.ssh_port);
|
||||
if (tmate_settings->ssh_port != 22)
|
||||
sprintf(port_arg, " -p%d", tmate_settings->ssh_port);
|
||||
|
||||
sprintf(tmp, "ssh%s ro-%s@%s", port_arg, tmate_session_token_ro, tmate_settings.tmate_host);
|
||||
sprintf(tmp, "ssh%s ro-%s@%s", port_arg, session->session_token_ro, tmate_settings->tmate_host);
|
||||
tmate_notify("Remote session read only: %s (clear your screen if you share this)", tmp);
|
||||
tmate_send_env("tmate_ssh_ro", tmp);
|
||||
|
||||
sprintf(tmp, "ssh%s %s@%s", port_arg, tmate_session_token, tmate_settings.tmate_host);
|
||||
sprintf(tmp, "ssh%s %s@%s", port_arg, session->session_token, tmate_settings->tmate_host);
|
||||
tmate_notify("Remote session: %s", tmp);
|
||||
tmate_send_env("tmate_ssh", tmp);
|
||||
|
||||
@ -231,7 +141,7 @@ static void tmate_sync_windows(struct session *s,
|
||||
server_redraw_window(wl->window);
|
||||
}
|
||||
|
||||
static void tmate_sync_layout(struct tmate_decoder *decoder,
|
||||
static void tmate_sync_layout(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct session *s;
|
||||
@ -254,7 +164,7 @@ static void tmate_sync_layout(struct tmate_decoder *decoder,
|
||||
tmate_sync_windows(s, uk);
|
||||
}
|
||||
|
||||
static void tmate_pty_data(struct tmate_decoder *decoder,
|
||||
static void tmate_pty_data(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
@ -263,7 +173,7 @@ static void tmate_pty_data(struct tmate_decoder *decoder,
|
||||
int id;
|
||||
|
||||
id = unpack_int(uk);
|
||||
unpack_raw(uk, &buf, &len);
|
||||
unpack_buffer(uk, &buf, &len);
|
||||
|
||||
wp = window_pane_find_by_id(id);
|
||||
if (!wp)
|
||||
@ -275,7 +185,7 @@ static void tmate_pty_data(struct tmate_decoder *decoder,
|
||||
wp->window->flags |= WINDOW_SILENCE;
|
||||
}
|
||||
|
||||
static void tmate_exec_cmd(struct tmate_decoder *decoder,
|
||||
static void tmate_exec_cmd(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct cmd_q *cmd_q;
|
||||
@ -297,7 +207,7 @@ out:
|
||||
free(cmd_str);
|
||||
}
|
||||
|
||||
static void tmate_failed_cmd(struct tmate_decoder *decoder,
|
||||
static void tmate_failed_cmd(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct client *c;
|
||||
@ -320,7 +230,7 @@ static void tmate_failed_cmd(struct tmate_decoder *decoder,
|
||||
free(cause);
|
||||
}
|
||||
|
||||
static void tmate_status(struct tmate_decoder *decoder,
|
||||
static void tmate_status(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct client *c;
|
||||
@ -342,7 +252,7 @@ extern void window_copy_redraw_screen(struct window_pane *);
|
||||
extern int window_copy_update_selection(struct window_pane *);
|
||||
extern void window_copy_init_for_output(struct window_pane *);
|
||||
|
||||
static void tmate_sync_copy_mode(struct tmate_decoder *decoder,
|
||||
static void tmate_sync_copy_mode(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct tmate_unpacker cm_uk, sel_uk, input_uk;
|
||||
@ -368,7 +278,7 @@ static void tmate_sync_copy_mode(struct tmate_decoder *decoder,
|
||||
return;
|
||||
}
|
||||
|
||||
if (decoder->protocol >= 2)
|
||||
if (session->client_protocol_version >= 2)
|
||||
base_backing = unpack_int(&cm_uk);
|
||||
|
||||
if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
|
||||
@ -388,7 +298,7 @@ static void tmate_sync_copy_mode(struct tmate_decoder *decoder,
|
||||
if (sel_uk.argc) {
|
||||
data->screen.sel.flag = 1;
|
||||
data->selx = unpack_int(&sel_uk);
|
||||
if (decoder->protocol >= 2) {
|
||||
if (session->client_protocol_version >= 2) {
|
||||
data->sely = -unpack_int(&sel_uk) + screen_hsize(data->backing)
|
||||
+ screen_size_y(data->backing)
|
||||
- 1;
|
||||
@ -424,7 +334,7 @@ static void tmate_sync_copy_mode(struct tmate_decoder *decoder,
|
||||
window_copy_redraw_screen(wp);
|
||||
}
|
||||
|
||||
static void tmate_write_copy_mode(struct tmate_decoder *decoder,
|
||||
static void tmate_write_copy_mode(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
@ -445,70 +355,21 @@ static void tmate_write_copy_mode(struct tmate_decoder *decoder,
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void handle_message(struct tmate_decoder *decoder, msgpack_object obj)
|
||||
void tmate_dispatch_daemon_message(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
struct tmate_unpacker _uk;
|
||||
struct tmate_unpacker *uk = &_uk;
|
||||
int cmd;
|
||||
|
||||
init_unpacker(uk, obj);
|
||||
|
||||
cmd = unpack_int(uk);
|
||||
|
||||
#if 0
|
||||
/* Really verbose tracers */
|
||||
if (cmd != TMATE_PTY_DATA) {
|
||||
msgpack_object_print(stderr, obj);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
#define dispatch(c, f) case c: f(session, uk); break
|
||||
|
||||
int cmd = unpack_int(uk);
|
||||
switch (cmd) {
|
||||
case TMATE_HEADER: tmate_header(decoder, uk); break;
|
||||
case TMATE_SYNC_LAYOUT: tmate_sync_layout(decoder, uk); break;
|
||||
case TMATE_PTY_DATA: tmate_pty_data(decoder, uk); break;
|
||||
case TMATE_EXEC_CMD: tmate_exec_cmd(decoder, uk); break;
|
||||
case TMATE_FAILED_CMD: tmate_failed_cmd(decoder, uk); break;
|
||||
case TMATE_STATUS: tmate_status(decoder, uk); break;
|
||||
case TMATE_SYNC_COPY_MODE: tmate_sync_copy_mode(decoder, uk); break;
|
||||
case TMATE_WRITE_COPY_MODE: tmate_write_copy_mode(decoder, uk); break;
|
||||
default: decoder_error();
|
||||
dispatch(TMATE_HEADER, tmate_header);
|
||||
dispatch(TMATE_SYNC_LAYOUT, tmate_sync_layout);
|
||||
dispatch(TMATE_PTY_DATA, tmate_pty_data);
|
||||
dispatch(TMATE_EXEC_CMD, tmate_exec_cmd);
|
||||
dispatch(TMATE_FAILED_CMD, tmate_failed_cmd);
|
||||
dispatch(TMATE_STATUS, tmate_status);
|
||||
dispatch(TMATE_SYNC_COPY_MODE, tmate_sync_copy_mode);
|
||||
dispatch(TMATE_WRITE_COPY_MODE, tmate_write_copy_mode);
|
||||
default: tmate_fatal("Bad message type: %d", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len)
|
||||
{
|
||||
msgpack_unpacked result;
|
||||
|
||||
msgpack_unpacker_buffer_consumed(&decoder->unpacker, len);
|
||||
|
||||
msgpack_unpacked_init(&result);
|
||||
while (msgpack_unpacker_next(&decoder->unpacker, &result)) {
|
||||
handle_message(decoder, result.data);
|
||||
}
|
||||
msgpack_unpacked_destroy(&result);
|
||||
|
||||
if (msgpack_unpacker_message_size(&decoder->unpacker) >
|
||||
TMATE_MAX_MESSAGE_SIZE) {
|
||||
tmate_fatal("Message too big");
|
||||
}
|
||||
}
|
||||
|
||||
void tmate_decoder_get_buffer(struct tmate_decoder *decoder,
|
||||
char **buf, size_t *len)
|
||||
{
|
||||
/* rewind the buffer if possible */
|
||||
if (msgpack_unpacker_buffer_capacity(&decoder->unpacker) <
|
||||
TMATE_MAX_MESSAGE_SIZE) {
|
||||
msgpack_unpacker_expand_buffer(&decoder->unpacker, 0);
|
||||
}
|
||||
|
||||
*buf = msgpack_unpacker_buffer(&decoder->unpacker);
|
||||
*len = msgpack_unpacker_buffer_capacity(&decoder->unpacker);
|
||||
}
|
||||
|
||||
void tmate_decoder_init(struct tmate_decoder *decoder)
|
||||
{
|
||||
if (!msgpack_unpacker_init(&decoder->unpacker, 2*TMATE_MAX_MESSAGE_SIZE))
|
||||
tmate_fatal("cannot initialize the unpacker");
|
||||
}
|
@ -1,36 +1,6 @@
|
||||
#include "tmate.h"
|
||||
|
||||
static int msgpack_write(void *data, const char *buf, unsigned int len)
|
||||
{
|
||||
struct tmate_encoder *encoder = data;
|
||||
|
||||
evbuffer_add(encoder->buffer, buf, len);
|
||||
|
||||
if ((encoder->ev_readable.ev_flags & EVLIST_INSERTED) &&
|
||||
!(encoder->ev_readable.ev_flags & EVLIST_ACTIVE)) {
|
||||
event_active(&encoder->ev_readable, EV_READ, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tmate_encoder_init(struct tmate_encoder *encoder)
|
||||
{
|
||||
encoder->buffer = evbuffer_new();
|
||||
msgpack_packer_init(&encoder->pk, encoder, &msgpack_write);
|
||||
}
|
||||
|
||||
#define msgpack_pack_string(pk, str) do { \
|
||||
int __strlen = strlen(str); \
|
||||
msgpack_pack_raw(pk, __strlen); \
|
||||
msgpack_pack_raw_body(pk, str, __strlen); \
|
||||
} while(0)
|
||||
|
||||
/* tmate_encoder may be NULL when replaying a session */
|
||||
#define pack(what, ...) do { \
|
||||
if (tmate_encoder) \
|
||||
msgpack_pack_##what(&tmate_encoder->pk, __VA_ARGS__); \
|
||||
} while(0)
|
||||
#define pack(what, ...) _pack(&tmate_session->client_encoder, what, __VA_ARGS__)
|
||||
|
||||
static void __tmate_notify(const char *msg)
|
||||
{
|
||||
@ -75,9 +45,9 @@ void printflike2 tmate_notify_later(int timeout, const char *fmt, ...)
|
||||
* multiple times.
|
||||
*/
|
||||
|
||||
evtimer_assign(&tmate_encoder->ev_notify_timer, ev_base,
|
||||
evtimer_assign(&tmate_session->ev_notify_timer, ev_base,
|
||||
__tmate_notify_later, msg);
|
||||
evtimer_add(&tmate_encoder->ev_notify_timer, &tv);
|
||||
evtimer_add(&tmate_session->ev_notify_timer, &tv);
|
||||
}
|
||||
|
||||
static int num_clients(void)
|
||||
@ -127,7 +97,7 @@ void tmate_notify_client_left(struct client *c)
|
||||
|
||||
void tmate_send_client_ready(void)
|
||||
{
|
||||
if (tmate_decoder && tmate_decoder->protocol < 4)
|
||||
if (tmate_session->client_protocol_version < 4)
|
||||
return;
|
||||
|
||||
pack(array, 1);
|
||||
@ -136,7 +106,7 @@ void tmate_send_client_ready(void)
|
||||
|
||||
void tmate_send_env(const char *name, const char *value)
|
||||
{
|
||||
if (tmate_decoder && tmate_decoder->protocol < 4)
|
||||
if (tmate_session->client_protocol_version < 4)
|
||||
return;
|
||||
|
||||
pack(array, 3);
|
@ -52,7 +52,7 @@ static int print_resolved_stack_frame(const char *frame)
|
||||
}
|
||||
#endif
|
||||
|
||||
void tmate_print_trace(void)
|
||||
void tmate_print_stack_trace(void)
|
||||
{
|
||||
void *array[20];
|
||||
size_t size;
|
||||
|
164
tmate-msgpack.c
Normal file
164
tmate-msgpack.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include "tmate.h"
|
||||
|
||||
static void on_encoder_buffer_ready(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
struct tmate_encoder *encoder = arg;
|
||||
|
||||
encoder->ev_active = false;
|
||||
encoder->ready_callback(encoder->userdata, encoder->buffer);
|
||||
}
|
||||
|
||||
static int on_encoder_write(void *userdata, const char *buf, unsigned int len)
|
||||
{
|
||||
struct tmate_encoder *encoder = userdata;
|
||||
|
||||
if (evbuffer_add(encoder->buffer, buf, len) < 0)
|
||||
tmate_fatal("Cannot buffer encoded data");
|
||||
|
||||
if (!encoder->ev_active) {
|
||||
event_active(&encoder->ev_buffer, EV_READ, 0);
|
||||
encoder->ev_active = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tmate_encoder_init(struct tmate_encoder *encoder,
|
||||
tmate_encoder_write_cb *callback,
|
||||
void *userdata)
|
||||
{
|
||||
msgpack_packer_init(&encoder->pk, encoder, &on_encoder_write);
|
||||
encoder->buffer = evbuffer_new();
|
||||
encoder->ready_callback = callback;
|
||||
encoder->userdata = userdata;
|
||||
|
||||
if (!encoder->buffer)
|
||||
tmate_fatal("Can't allocate buffer");
|
||||
|
||||
event_assign(&encoder->ev_buffer, ev_base, -1,
|
||||
EV_READ | EV_PERSIST, on_encoder_buffer_ready, encoder);
|
||||
|
||||
event_add(&encoder->ev_buffer, NULL);
|
||||
|
||||
encoder->ev_active = false;
|
||||
}
|
||||
|
||||
static void decoder_error(void)
|
||||
{
|
||||
tmate_print_stack_trace();
|
||||
tmate_fatal("Received a bad message");
|
||||
}
|
||||
|
||||
void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj)
|
||||
{
|
||||
if (obj.type != MSGPACK_OBJECT_ARRAY)
|
||||
decoder_error();
|
||||
|
||||
uk->argv = obj.via.array.ptr;
|
||||
uk->argc = obj.via.array.size;
|
||||
}
|
||||
|
||||
int64_t unpack_int(struct tmate_unpacker *uk)
|
||||
{
|
||||
int64_t val;
|
||||
|
||||
if (uk->argc == 0)
|
||||
decoder_error();
|
||||
|
||||
if (uk->argv[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER &&
|
||||
uk->argv[0].type != MSGPACK_OBJECT_NEGATIVE_INTEGER)
|
||||
decoder_error();
|
||||
|
||||
val = uk->argv[0].via.i64;
|
||||
|
||||
uk->argv++;
|
||||
uk->argc--;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len)
|
||||
{
|
||||
if (uk->argc == 0)
|
||||
decoder_error();
|
||||
|
||||
#if NEW_MSGPACK_API
|
||||
if (uk->argv[0].type != MSGPACK_OBJECT_STR &&
|
||||
uk->argv[0].type != MSGPACK_OBJECT_BIN)
|
||||
decoder_error();
|
||||
|
||||
*len = uk->argv[0].via.str.size;
|
||||
*buf = uk->argv[0].via.str.ptr;
|
||||
#else
|
||||
if (uk->argv[0].type != MSGPACK_OBJECT_RAW)
|
||||
decoder_error();
|
||||
|
||||
*len = uk->argv[0].via.raw.size;
|
||||
*buf = uk->argv[0].via.raw.ptr;
|
||||
#endif
|
||||
|
||||
uk->argv++;
|
||||
uk->argc--;
|
||||
}
|
||||
|
||||
char *unpack_string(struct tmate_unpacker *uk)
|
||||
{
|
||||
const char *buf;
|
||||
char *alloc_buf;
|
||||
size_t len;
|
||||
|
||||
unpack_buffer(uk, &buf, &len);
|
||||
|
||||
alloc_buf = xmalloc(len + 1);
|
||||
memcpy(alloc_buf, buf, len);
|
||||
alloc_buf[len] = '\0';
|
||||
|
||||
return alloc_buf;
|
||||
}
|
||||
|
||||
void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested)
|
||||
{
|
||||
if (uk->argc == 0)
|
||||
decoder_error();
|
||||
|
||||
init_unpacker(nested, uk->argv[0]);
|
||||
|
||||
uk->argv++;
|
||||
uk->argc--;
|
||||
}
|
||||
|
||||
void tmate_decoder_init(struct tmate_decoder *decoder, tmate_decoder_reader *reader,
|
||||
void *userdata)
|
||||
{
|
||||
if (!msgpack_unpacker_init(&decoder->unpacker, TMATE_MAX_MESSAGE_SIZE))
|
||||
tmate_fatal("Cannot initialize the unpacker");
|
||||
decoder->reader = reader;
|
||||
decoder->userdata = userdata;
|
||||
}
|
||||
|
||||
void tmate_decoder_get_buffer(struct tmate_decoder *decoder,
|
||||
char **buf, size_t *len)
|
||||
{
|
||||
ssize_t current_size = msgpack_unpacker_message_size(&decoder->unpacker);
|
||||
if (!msgpack_unpacker_reserve_buffer(&decoder->unpacker,
|
||||
TMATE_MAX_MESSAGE_SIZE - current_size))
|
||||
tmate_fatal("cannot expand decoder buffer");
|
||||
|
||||
*buf = msgpack_unpacker_buffer(&decoder->unpacker);
|
||||
*len = msgpack_unpacker_buffer_capacity(&decoder->unpacker);
|
||||
}
|
||||
|
||||
void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len)
|
||||
{
|
||||
struct tmate_unpacker _uk, *uk = &_uk;
|
||||
msgpack_unpacked result;
|
||||
|
||||
msgpack_unpacker_buffer_consumed(&decoder->unpacker, len);
|
||||
|
||||
msgpack_unpacked_init(&result);
|
||||
while (msgpack_unpacker_next(&decoder->unpacker, &result)) {
|
||||
init_unpacker(uk, result.data);
|
||||
decoder->reader(decoder->userdata, uk);
|
||||
}
|
||||
msgpack_unpacked_destroy(&result);
|
||||
}
|
139
tmate-slave.c
139
tmate-slave.c
@ -16,13 +16,10 @@
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sched.h>
|
||||
#include "tmate.h"
|
||||
|
||||
struct tmate_decoder *tmate_decoder;
|
||||
struct tmate_encoder *tmate_encoder;
|
||||
int tmux_socket_fd;
|
||||
const char *tmate_session_token;
|
||||
const char *tmate_session_token_ro;
|
||||
struct tmate_session _tmate_session, *tmate_session = &_tmate_session;
|
||||
|
||||
extern FILE *log_file;
|
||||
|
||||
@ -33,7 +30,7 @@ static int dev_urandom_fd;
|
||||
extern int server_create_socket(void);
|
||||
extern int client_connect(char *path, int start_server);
|
||||
|
||||
struct tmate_settings tmate_settings = {
|
||||
struct tmate_settings _tmate_settings = {
|
||||
.keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR,
|
||||
.ssh_port = TMATE_SSH_DEFAULT_PORT,
|
||||
.master_hostname = TMATE_DEFAULT_MASTER_HOST,
|
||||
@ -43,6 +40,8 @@ struct tmate_settings tmate_settings = {
|
||||
.use_syslog = false,
|
||||
};
|
||||
|
||||
struct tmate_settings *tmate_settings = &_tmate_settings;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: tmate-slave [-k keys_dir] [-p port] [-m master_hostname] [-q master_port] [-s] [-v]\n");
|
||||
@ -61,6 +60,18 @@ long tmate_get_random_long(void)
|
||||
return val;
|
||||
}
|
||||
|
||||
extern int server_shutdown;
|
||||
extern int server_fd;
|
||||
extern void server_send_shutdown(void);
|
||||
void request_server_termination(void)
|
||||
{
|
||||
if (server_fd) {
|
||||
server_shutdown = 1;
|
||||
server_send_shutdown();
|
||||
} else
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
int opt;
|
||||
@ -68,25 +79,25 @@ int main(int argc, char **argv, char **envp)
|
||||
while ((opt = getopt(argc, argv, "k:p:lvm:q:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'p':
|
||||
tmate_settings.ssh_port = atoi(optarg);
|
||||
tmate_settings->ssh_port = atoi(optarg);
|
||||
break;
|
||||
case 'k':
|
||||
tmate_settings.keys_dir = xstrdup(optarg);
|
||||
tmate_settings->keys_dir = xstrdup(optarg);
|
||||
break;
|
||||
case 's':
|
||||
tmate_settings.use_syslog = true;
|
||||
tmate_settings->use_syslog = true;
|
||||
break;
|
||||
case 'v':
|
||||
tmate_settings.log_level++;
|
||||
tmate_settings->log_level++;
|
||||
break;
|
||||
case 'm':
|
||||
tmate_settings.master_hostname = xstrdup(optarg);
|
||||
tmate_settings->master_hostname = xstrdup(optarg);
|
||||
break;
|
||||
case 'q':
|
||||
tmate_settings.master_port = atoi(optarg);
|
||||
tmate_settings->master_port = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
tmate_settings.tmate_host = xstrdup(optarg);
|
||||
tmate_settings->tmate_host = xstrdup(optarg);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
@ -94,18 +105,18 @@ int main(int argc, char **argv, char **envp)
|
||||
}
|
||||
}
|
||||
|
||||
if (!tmate_settings.tmate_host) {
|
||||
if (!tmate_settings->tmate_host) {
|
||||
char hostname[255];
|
||||
if (gethostname(hostname, sizeof(hostname)) < 0)
|
||||
tmate_fatal("cannot get hostname");
|
||||
tmate_settings.tmate_host = xstrdup(hostname);
|
||||
tmate_settings->tmate_host = xstrdup(hostname);
|
||||
}
|
||||
|
||||
cmdline = *argv;
|
||||
cmdline_end = *envp;
|
||||
|
||||
init_logging("tmate-ssh",
|
||||
tmate_settings.use_syslog, tmate_settings.log_level);
|
||||
tmate_settings->use_syslog, tmate_settings->log_level);
|
||||
|
||||
tmate_preload_trace_lib();
|
||||
|
||||
@ -117,7 +128,8 @@ int main(int argc, char **argv, char **envp)
|
||||
(mkdir(TMATE_WORKDIR "/jail", 0700) < 0 && errno != EEXIST))
|
||||
tmate_fatal("Cannot prepare session in " TMATE_WORKDIR);
|
||||
|
||||
tmate_ssh_server_main(tmate_settings.keys_dir, tmate_settings.ssh_port);
|
||||
tmate_ssh_server_main(tmate_session,
|
||||
tmate_settings->keys_dir, tmate_settings->ssh_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -139,33 +151,33 @@ static char *get_random_token(void)
|
||||
return token;
|
||||
}
|
||||
|
||||
static void set_session_token(struct tmate_ssh_client *client,
|
||||
static void set_session_token(struct tmate_session *session,
|
||||
const char *token)
|
||||
{
|
||||
tmate_session_token = xstrdup(token);
|
||||
session->session_token = xstrdup(token);
|
||||
strcpy(socket_path, TMATE_WORKDIR "/sessions/");
|
||||
strcat(socket_path, token);
|
||||
|
||||
memset(cmdline, 0, cmdline_end - cmdline);
|
||||
sprintf(cmdline, "tmate-slave [%s] %s %s",
|
||||
tmate_session_token,
|
||||
client->role == TMATE_ROLE_SERVER ? "(server)" : "(client)",
|
||||
client->ip_address);
|
||||
session->session_token,
|
||||
session->ssh_client.role == TMATE_ROLE_SERVER ? "(server)" : "(client)",
|
||||
session->ssh_client.ip_address);
|
||||
}
|
||||
static void create_session_ro_symlink(void)
|
||||
static void create_session_ro_symlink(struct tmate_session *session)
|
||||
{
|
||||
char session_ro_path[MAXPATHLEN];
|
||||
|
||||
tmate_session_token_ro = get_random_token();
|
||||
session->session_token_ro = get_random_token();
|
||||
#ifdef DEVENV
|
||||
strcpy((char *)tmate_session_token_ro, "READONLYTOKENFORDEVENV000");
|
||||
strcpy((char *)session->session_token_ro, "READONLYTOKENFORDEVENV000");
|
||||
#endif
|
||||
|
||||
strcpy(session_ro_path, TMATE_WORKDIR "/sessions/");
|
||||
strcat(session_ro_path, tmate_session_token_ro);
|
||||
strcat(session_ro_path, session->session_token_ro);
|
||||
|
||||
unlink(session_ro_path);
|
||||
if (symlink(tmate_session_token, session_ro_path) < 0)
|
||||
if (symlink(session->session_token, session_ro_path) < 0)
|
||||
tmate_fatal("Cannot create read-only symlink");
|
||||
}
|
||||
|
||||
@ -250,9 +262,8 @@ static void jail(void)
|
||||
uid = pw->pw_uid;
|
||||
gid = pw->pw_gid;
|
||||
|
||||
/*
|
||||
* We are already in a new PID namespace (from the server fork).
|
||||
*/
|
||||
if (getuid() != 0)
|
||||
tmate_fatal("Need root priviledges");
|
||||
|
||||
if (chroot(TMATE_WORKDIR "/jail") < 0)
|
||||
tmate_fatal("Cannot chroot()");
|
||||
@ -260,6 +271,9 @@ static void jail(void)
|
||||
if (chdir("/") < 0)
|
||||
tmate_fatal("Cannot chdir()");
|
||||
|
||||
if (unshare(CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWNET) < 0)
|
||||
tmate_fatal("Cannot create new namespace");
|
||||
|
||||
if (setgroups(1, (gid_t[]){gid}) < 0)
|
||||
tmate_fatal("Cannot setgroups()");
|
||||
|
||||
@ -272,8 +286,8 @@ static void jail(void)
|
||||
if (nice(1) < 0)
|
||||
tmate_fatal("Cannot nice()");
|
||||
|
||||
tmate_debug("Dropped priviledges to %s (%d,%d)",
|
||||
TMATE_JAIL_USER, uid, gid);
|
||||
tmate_debug("Dropped priviledges to %s (%d,%d), jailed in %s",
|
||||
TMATE_JAIL_USER, uid, gid, TMATE_WORKDIR "/jail");
|
||||
}
|
||||
|
||||
static void setup_ncurse(int fd, const char *name)
|
||||
@ -283,8 +297,10 @@ static void setup_ncurse(int fd, const char *name)
|
||||
tmate_fatal("Cannot setup terminal");
|
||||
}
|
||||
|
||||
static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
||||
static void tmate_spawn_slave_server(struct tmate_session *session)
|
||||
{
|
||||
struct tmate_ssh_client *client = &session->ssh_client;
|
||||
|
||||
char *token;
|
||||
struct tmate_encoder encoder;
|
||||
struct tmate_decoder decoder;
|
||||
@ -294,17 +310,17 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
||||
strcpy(token, "SUPERSECURETOKENFORDEVENV");
|
||||
#endif
|
||||
|
||||
set_session_token(client, token);
|
||||
set_session_token(session, token);
|
||||
free(token);
|
||||
|
||||
tmate_debug("Spawning slave server for %s at %s (%s)",
|
||||
client->username, client->ip_address, client->pubkey);
|
||||
|
||||
tmux_socket_fd = server_create_socket();
|
||||
if (tmux_socket_fd < 0)
|
||||
session->tmux_socket_fd = server_create_socket();
|
||||
if (session->tmux_socket_fd < 0)
|
||||
tmate_fatal("Cannot create to the tmux socket");
|
||||
|
||||
create_session_ro_symlink();
|
||||
create_session_ro_symlink(session);
|
||||
|
||||
/*
|
||||
* Needed to initialize the database used in tty-term.c.
|
||||
@ -312,27 +328,23 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
||||
*/
|
||||
setup_ncurse(STDOUT_FILENO, "screen-256color");
|
||||
|
||||
close_fds_except((int[]){tmux_socket_fd,
|
||||
ssh_get_fd(client->session),
|
||||
close_fds_except((int[]){session->tmux_socket_fd,
|
||||
ssh_get_fd(session->ssh_client.session),
|
||||
log_file ? fileno(log_file) : -1}, 3);
|
||||
|
||||
jail();
|
||||
|
||||
ev_base = osdep_event_init();
|
||||
event_reinit(ev_base);
|
||||
|
||||
tmate_encoder_init(&encoder);
|
||||
tmate_decoder_init(&decoder);
|
||||
tmate_encoder = &encoder;
|
||||
tmate_decoder = &decoder;
|
||||
|
||||
tmate_ssh_client_init(client, &encoder, &decoder);
|
||||
tmate_daemon_init(session);
|
||||
|
||||
tmux_server_init(IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
||||
/* never reached */
|
||||
}
|
||||
|
||||
static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
||||
static void tmate_spawn_slave_client(struct tmate_session *session)
|
||||
{
|
||||
struct tmate_ssh_client *client = &session->ssh_client;
|
||||
char *argv_rw[] = {(char *)"attach", NULL};
|
||||
char *argv_ro[] = {(char *)"attach", (char *)"-r", NULL};
|
||||
char **argv = argv_rw;
|
||||
@ -351,13 +363,13 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
||||
tmate_fatal("Invalid token");
|
||||
}
|
||||
|
||||
set_session_token(client, token);
|
||||
set_session_token(session, token);
|
||||
|
||||
tmate_debug("Spawning slave client for %s (%s)",
|
||||
client->ip_address, client->pubkey);
|
||||
|
||||
tmux_socket_fd = client_connect(socket_path, 0);
|
||||
if (tmux_socket_fd < 0) {
|
||||
session->tmux_socket_fd = client_connect(socket_path, 0);
|
||||
if (session->tmux_socket_fd < 0) {
|
||||
random_sleep(); /* for making timing attacks harder */
|
||||
ssh_echo(client, EXPIRED_TOKEN_ERROR_STR);
|
||||
tmate_fatal("Expired token");
|
||||
@ -370,16 +382,16 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
||||
* 2) We prevent any input (aside from the window size) to go through
|
||||
* to the server.
|
||||
*/
|
||||
client->readonly = 0;
|
||||
session->readonly = false;
|
||||
if (lstat(socket_path, &fstat) < 0)
|
||||
tmate_fatal("Cannot fstat()");
|
||||
if (S_ISLNK(fstat.st_mode)) {
|
||||
client->readonly = 1;
|
||||
session->readonly = true;
|
||||
argv = argv_ro;
|
||||
argc = 2;
|
||||
}
|
||||
|
||||
if (openpty(&client->pty, &slave_pty, NULL, NULL, NULL) < 0)
|
||||
if (openpty(&session->pty, &slave_pty, NULL, NULL, NULL) < 0)
|
||||
tmate_fatal("Cannot allocate pty");
|
||||
|
||||
dup2(slave_pty, STDIN_FILENO);
|
||||
@ -388,23 +400,24 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
||||
|
||||
setup_ncurse(slave_pty, "screen-256color");
|
||||
close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
|
||||
tmux_socket_fd, ssh_get_fd(client->session),
|
||||
client->pty, log_file ? fileno(log_file) : -1}, 7);
|
||||
session->tmux_socket_fd,
|
||||
ssh_get_fd(session->ssh_client.session),
|
||||
session->pty, log_file ? fileno(log_file) : -1}, 7);
|
||||
jail();
|
||||
event_reinit(ev_base);
|
||||
|
||||
ev_base = osdep_event_init();
|
||||
|
||||
tmate_ssh_client_pty_init(client);
|
||||
tmate_ssh_client_pty_init(session);
|
||||
|
||||
ret = client_main(argc, argv, IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
||||
tmate_flush_pty(client);
|
||||
tmate_flush_pty(session);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
void tmate_spawn_slave(struct tmate_ssh_client *client)
|
||||
void tmate_spawn_slave(struct tmate_session *session)
|
||||
{
|
||||
if (client->role == TMATE_ROLE_SERVER)
|
||||
tmate_spawn_slave_server(client);
|
||||
|
||||
if (session->ssh_client.role == TMATE_ROLE_SERVER)
|
||||
tmate_spawn_slave_server(session);
|
||||
else
|
||||
tmate_spawn_slave_client(client);
|
||||
tmate_spawn_slave_client(session);
|
||||
}
|
||||
|
@ -1,62 +1,40 @@
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <errno.h>
|
||||
#include "tmate.h"
|
||||
|
||||
extern void client_write_server(enum msgtype type, void *buf, size_t len);
|
||||
|
||||
static void consume_channel(struct tmate_ssh_client *client)
|
||||
static int on_ssh_channel_read(ssh_session _session, ssh_channel channel,
|
||||
void *_data, uint32_t total_len,
|
||||
int is_stderr, void *userdata)
|
||||
{
|
||||
ssize_t len, written;
|
||||
char buf[4096];
|
||||
char *ptr;
|
||||
struct tmate_session *session = userdata;
|
||||
char *data = _data;
|
||||
size_t written = 0;
|
||||
ssize_t len;
|
||||
|
||||
for (;;) {
|
||||
len = ssh_channel_read_nonblocking(client->channel,
|
||||
buf, sizeof(buf), 0);
|
||||
if (len < 0) {
|
||||
if (!ssh_is_connected(client->session))
|
||||
tmate_fatal("Disconnected");
|
||||
if (session->readonly)
|
||||
return total_len;
|
||||
|
||||
tmate_fatal("Error reading from channel: %s",
|
||||
ssh_get_error(client->session));
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (client->readonly)
|
||||
continue;
|
||||
|
||||
ptr = buf;
|
||||
setblocking(client->pty, 1);
|
||||
while (len > 0) {
|
||||
written = write(client->pty, ptr, len);
|
||||
if (written < 0)
|
||||
setblocking(session->pty, 1);
|
||||
while (total_len) {
|
||||
len = write(session->pty, data, total_len);
|
||||
if (len < 0)
|
||||
tmate_fatal("Error writing to pty");
|
||||
|
||||
ptr += written;
|
||||
len -= written;
|
||||
}
|
||||
setblocking(client->pty, 0);
|
||||
total_len -= len;
|
||||
written += len;
|
||||
data += len;
|
||||
}
|
||||
setblocking(session->pty, 0);
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static void on_session_event(struct tmate_ssh_client *client)
|
||||
static int on_ssh_message_callback(ssh_session _session, ssh_message msg, void *arg)
|
||||
{
|
||||
ssh_execute_message_callbacks(client->session);
|
||||
consume_channel(client);
|
||||
}
|
||||
struct tmate_session *session = arg;
|
||||
|
||||
static void __on_session_event(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
on_session_event(arg);
|
||||
}
|
||||
|
||||
static int message_callback(struct tmate_ssh_client *client,
|
||||
ssh_message msg)
|
||||
{
|
||||
if (ssh_message_type(msg) == SSH_REQUEST_CHANNEL &&
|
||||
ssh_message_subtype(msg) == SSH_CHANNEL_REQUEST_WINDOW_CHANGE) {
|
||||
struct winsize ws;
|
||||
@ -64,7 +42,7 @@ static int message_callback(struct tmate_ssh_client *client,
|
||||
ws.ws_col = ssh_message_channel_request_pty_width(msg);
|
||||
ws.ws_row = ssh_message_channel_request_pty_height(msg);
|
||||
|
||||
ioctl(client->pty, TIOCSWINSZ, &ws);
|
||||
ioctl(session->pty, TIOCSWINSZ, &ws);
|
||||
client_write_server(MSG_RESIZE, NULL, 0);
|
||||
|
||||
return 1;
|
||||
@ -72,27 +50,13 @@ static int message_callback(struct tmate_ssh_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __message_callback(ssh_session session, ssh_message msg, void *arg)
|
||||
{
|
||||
return message_callback(arg, msg);
|
||||
}
|
||||
|
||||
static void register_session_fd_event(struct tmate_ssh_client *client)
|
||||
{
|
||||
ssh_set_message_callback(client->session, __message_callback, client);
|
||||
|
||||
event_assign(&client->ev_ssh, ev_base, ssh_get_fd(client->session),
|
||||
EV_READ | EV_PERSIST, __on_session_event, client);
|
||||
event_add(&client->ev_ssh, NULL);
|
||||
}
|
||||
|
||||
static void on_pty_event(struct tmate_ssh_client *client)
|
||||
static void on_pty_event(struct tmate_session *session)
|
||||
{
|
||||
ssize_t len, written;
|
||||
char buf[4096];
|
||||
|
||||
for (;;) {
|
||||
len = read(client->pty, buf, sizeof(buf));
|
||||
len = read(session->pty, buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return;
|
||||
@ -102,10 +66,10 @@ static void on_pty_event(struct tmate_ssh_client *client)
|
||||
if (len == 0)
|
||||
tmate_fatal("pty reached EOF");
|
||||
|
||||
written = ssh_channel_write(client->channel, buf, len);
|
||||
written = ssh_channel_write(session->ssh_client.channel, buf, len);
|
||||
if (written < 0)
|
||||
tmate_fatal("Error writing to channel: %s",
|
||||
ssh_get_error(client->session));
|
||||
ssh_get_error(session->ssh_client.session));
|
||||
if (len != written)
|
||||
tmate_fatal("Cannot write %d bytes, wrote %d",
|
||||
(int)len, (int)written);
|
||||
@ -117,25 +81,29 @@ static void __on_pty_event(evutil_socket_t fd, short what, void *arg)
|
||||
on_pty_event(arg);
|
||||
}
|
||||
|
||||
void tmate_flush_pty(struct tmate_ssh_client *client)
|
||||
void tmate_flush_pty(struct tmate_session *session)
|
||||
{
|
||||
on_pty_event(client);
|
||||
close(client->pty);
|
||||
on_pty_event(session);
|
||||
close(session->pty);
|
||||
}
|
||||
|
||||
static void register_pty_event(struct tmate_ssh_client *client)
|
||||
void tmate_ssh_client_pty_init(struct tmate_session *session)
|
||||
{
|
||||
setblocking(client->pty, 0);
|
||||
event_assign(&client->ev_pty, ev_base, client->pty,
|
||||
EV_READ | EV_PERSIST, __on_pty_event, client);
|
||||
event_add(&client->ev_pty, NULL);
|
||||
}
|
||||
struct tmate_ssh_client *client = &session->ssh_client;
|
||||
|
||||
void tmate_ssh_client_pty_init(struct tmate_ssh_client *client)
|
||||
{
|
||||
ioctl(client->pty, TIOCSWINSZ, &client->winsize_pty);
|
||||
register_session_fd_event(client);
|
||||
register_pty_event(client);
|
||||
ioctl(session->pty, TIOCSWINSZ, &session->ssh_client.winsize_pty);
|
||||
|
||||
tmate_start_keepalive_timer(client);
|
||||
memset(&client->channel_cb, 0, sizeof(client->channel_cb));
|
||||
ssh_callbacks_init(&client->channel_cb);
|
||||
client->channel_cb.userdata = session;
|
||||
client->channel_cb.channel_data_function = on_ssh_channel_read,
|
||||
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
||||
|
||||
ssh_set_message_callback(session->ssh_client.session,
|
||||
on_ssh_message_callback, session);
|
||||
|
||||
setblocking(session->pty, 0);
|
||||
event_assign(&session->ev_pty, ev_base, session->pty,
|
||||
EV_READ | EV_PERSIST, __on_pty_event, session);
|
||||
event_add(&session->ev_pty, NULL);
|
||||
}
|
||||
|
@ -1,116 +1,77 @@
|
||||
#include "tmate.h"
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
|
||||
extern int server_shutdown;
|
||||
extern void server_send_shutdown(void);
|
||||
|
||||
#define request_termination(str, ...) do { \
|
||||
tmate_info(str, ## __VA_ARGS__); \
|
||||
server_shutdown = 1; \
|
||||
server_send_shutdown(); \
|
||||
} while(0)
|
||||
|
||||
static void consume_channel(struct tmate_ssh_client *client)
|
||||
static void on_decoder_read(void *userdata, struct tmate_unpacker *uk)
|
||||
{
|
||||
struct tmate_session *session = userdata;
|
||||
tmate_dispatch_daemon_message(session, uk);
|
||||
}
|
||||
|
||||
static int on_ssh_channel_read(ssh_session _session, ssh_channel channel,
|
||||
void *_data, uint32_t total_len,
|
||||
int is_stderr, void *userdata)
|
||||
{
|
||||
struct tmate_session *session = userdata;
|
||||
char *data = _data;
|
||||
size_t written = 0;
|
||||
char *buf;
|
||||
ssize_t len;
|
||||
size_t len;
|
||||
|
||||
for (;;) {
|
||||
tmate_decoder_get_buffer(client->decoder, &buf, &len);
|
||||
if (len == 0) {
|
||||
request_termination("Decoder buffer full");
|
||||
break;
|
||||
}
|
||||
while (total_len) {
|
||||
tmate_decoder_get_buffer(&session->client_decoder, &buf, &len);
|
||||
|
||||
len = ssh_channel_read_nonblocking(client->channel,
|
||||
buf, len, 0);
|
||||
if (len < 0) {
|
||||
if (!ssh_is_connected(client->session))
|
||||
request_termination("Disconnected");
|
||||
else
|
||||
request_termination("Error reading from channel: %s",
|
||||
ssh_get_error(client->session));
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
tmate_fatal("No more room in client decoder. Message too big?");
|
||||
|
||||
tmate_decoder_commit(client->decoder, len);
|
||||
}
|
||||
if (len > total_len)
|
||||
len = total_len;
|
||||
|
||||
memcpy(buf, data, len);
|
||||
|
||||
tmate_decoder_commit(&session->client_decoder, len);
|
||||
|
||||
total_len -= len;
|
||||
written += len;
|
||||
data += len;
|
||||
}
|
||||
|
||||
static void on_session_event(struct tmate_ssh_client *client)
|
||||
return written;
|
||||
}
|
||||
|
||||
static void on_encoder_write(void *userdata, struct evbuffer *buffer)
|
||||
{
|
||||
ssh_execute_message_callbacks(client->session);
|
||||
consume_channel(client);
|
||||
}
|
||||
|
||||
static void __on_session_event(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
on_session_event(arg);
|
||||
}
|
||||
|
||||
static void register_session_fd_event(struct tmate_ssh_client *client)
|
||||
{
|
||||
event_assign(&client->ev_ssh, ev_base, ssh_get_fd(client->session),
|
||||
EV_READ | EV_PERSIST, __on_session_event, client);
|
||||
event_add(&client->ev_ssh, NULL);
|
||||
}
|
||||
|
||||
static void flush_input_stream(struct tmate_ssh_client *client)
|
||||
{
|
||||
struct evbuffer *evb = client->encoder->buffer;
|
||||
struct tmate_session *session = userdata;
|
||||
ssize_t len, written;
|
||||
char *buf;
|
||||
|
||||
if (server_shutdown)
|
||||
return;
|
||||
|
||||
for(;;) {
|
||||
len = evbuffer_get_length(evb);
|
||||
len = evbuffer_get_length(buffer);
|
||||
if (!len)
|
||||
break;
|
||||
|
||||
buf = evbuffer_pullup(evb, -1);
|
||||
buf = evbuffer_pullup(buffer, -1);
|
||||
|
||||
written = ssh_channel_write(client->channel, buf, len);
|
||||
written = ssh_channel_write(session->ssh_client.channel, buf, len);
|
||||
if (written < 0) {
|
||||
request_termination("Error writing to channel: %s",
|
||||
ssh_get_error(client->session));
|
||||
tmate_warn("Error writing to channel: %s",
|
||||
ssh_get_error(session->ssh_client.session));
|
||||
request_server_termination();
|
||||
break;
|
||||
}
|
||||
|
||||
evbuffer_drain(evb, written);
|
||||
evbuffer_drain(buffer, written);
|
||||
}
|
||||
}
|
||||
|
||||
static void __flush_input_stream(evutil_socket_t fd, short what, void *arg)
|
||||
void tmate_daemon_init(struct tmate_session *session)
|
||||
{
|
||||
flush_input_stream(arg);
|
||||
}
|
||||
|
||||
static void register_input_stream_event(struct tmate_ssh_client *client)
|
||||
{
|
||||
event_assign(&client->encoder->ev_readable, ev_base, -1,
|
||||
EV_READ | EV_PERSIST, __flush_input_stream, client);
|
||||
event_add(&client->encoder->ev_readable, NULL);
|
||||
}
|
||||
|
||||
|
||||
void tmate_ssh_client_init(struct tmate_ssh_client *client,
|
||||
struct tmate_encoder *encoder,
|
||||
struct tmate_decoder *decoder)
|
||||
{
|
||||
client->winsize_pty.ws_col = 80;
|
||||
client->winsize_pty.ws_row = 24;
|
||||
|
||||
client->encoder = encoder;
|
||||
client->decoder = decoder;
|
||||
|
||||
register_session_fd_event(client);
|
||||
register_input_stream_event(client);
|
||||
|
||||
tmate_start_keepalive_timer(client);
|
||||
struct tmate_ssh_client *client = &session->ssh_client;
|
||||
|
||||
memset(&client->channel_cb, 0, sizeof(client->channel_cb));
|
||||
ssh_callbacks_init(&client->channel_cb);
|
||||
client->channel_cb.userdata = session;
|
||||
client->channel_cb.channel_data_function = on_ssh_channel_read,
|
||||
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
||||
|
||||
tmate_encoder_init(&session->client_encoder, on_encoder_write, session);
|
||||
tmate_decoder_init(&session->client_decoder, on_decoder_read, session);
|
||||
}
|
||||
|
@ -4,28 +4,24 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <event.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "tmate.h"
|
||||
|
||||
#define SSH_GRACE_PERIOD 60
|
||||
|
||||
static void start_keepalive_timer(struct tmate_ssh_client *client);
|
||||
static void on_keepalive_timer(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
struct tmate_ssh_client *client = arg;
|
||||
|
||||
ssh_send_keepalive(client->session);
|
||||
tmate_start_keepalive_timer(client);
|
||||
start_keepalive_timer(client);
|
||||
}
|
||||
|
||||
void tmate_start_keepalive_timer(struct tmate_ssh_client *client)
|
||||
static void start_keepalive_timer(struct tmate_ssh_client *client)
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = TMATE_KEEPALIVE;
|
||||
tv.tv_usec = 0;
|
||||
struct timeval tv = { TMATE_SSH_KEEPALIVE, 0 };
|
||||
|
||||
evtimer_assign(&client->ev_keepalive_timer, ev_base,
|
||||
on_keepalive_timer, client);
|
||||
@ -65,12 +61,6 @@ static int subsystem_request(ssh_session session, ssh_channel channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ssh_channel_callbacks_struct ssh_channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request,
|
||||
.channel_subsystem_request_function = subsystem_request,
|
||||
};
|
||||
|
||||
static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
|
||||
{
|
||||
struct tmate_ssh_client *client = userdata;
|
||||
@ -89,9 +79,13 @@ static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
|
||||
if (!client->channel)
|
||||
tmate_fatal("Error getting channel");
|
||||
|
||||
ssh_channel_cb.userdata = client;
|
||||
ssh_callbacks_init(&ssh_channel_cb);
|
||||
ssh_set_channel_callbacks(client->channel, &ssh_channel_cb);
|
||||
memset(&client->channel_cb, 0, sizeof(client->channel_cb));
|
||||
ssh_callbacks_init(&client->channel_cb);
|
||||
client->channel_cb.userdata = client;
|
||||
client->channel_cb.channel_pty_request_function = pty_request,
|
||||
client->channel_cb.channel_shell_request_function = shell_request,
|
||||
client->channel_cb.channel_subsystem_request_function = subsystem_request,
|
||||
ssh_set_channel_callbacks(client->channel, &client->channel_cb);
|
||||
|
||||
return client->channel;
|
||||
}
|
||||
@ -121,16 +115,39 @@ static struct ssh_server_callbacks_struct ssh_server_cb = {
|
||||
.channel_open_request_session_function = channel_open_request_cb,
|
||||
};
|
||||
|
||||
static void client_bootstrap(struct tmate_ssh_client *client)
|
||||
static void on_ssh_read(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
struct tmate_ssh_client *client = arg;
|
||||
ssh_execute_message_callbacks(client->session);
|
||||
|
||||
if (!ssh_is_connected(client->session)) {
|
||||
tmate_warn("SSH Disconnected");
|
||||
|
||||
/* For graceful tmux client termination */
|
||||
request_server_termination();
|
||||
}
|
||||
}
|
||||
|
||||
static void register_on_ssh_read(struct tmate_ssh_client *client)
|
||||
{
|
||||
event_assign(&client->ev_ssh, ev_base, ssh_get_fd(client->session),
|
||||
EV_READ | EV_PERSIST, on_ssh_read, client);
|
||||
event_add(&client->ev_ssh, NULL);
|
||||
}
|
||||
|
||||
static void client_bootstrap(struct tmate_session *_session)
|
||||
{
|
||||
struct tmate_ssh_client *client = &_session->ssh_client;
|
||||
int auth = 0;
|
||||
int grace_period = SSH_GRACE_PERIOD;
|
||||
int grace_period = TMATE_SSH_GRACE_PERIOD;
|
||||
ssh_event mainloop;
|
||||
ssh_session session = client->session;
|
||||
ssh_message msg;
|
||||
|
||||
tmate_notice("Bootstrapping ssh client ip=%s", client->ip_address);
|
||||
|
||||
ev_base = osdep_event_init();
|
||||
|
||||
/* new process group, we don't want to die with our parent (upstart) */
|
||||
setpgid(0, 0);
|
||||
|
||||
@ -163,7 +180,11 @@ static void client_bootstrap(struct tmate_ssh_client *client)
|
||||
}
|
||||
|
||||
alarm(0);
|
||||
tmate_spawn_slave(client);
|
||||
|
||||
start_keepalive_timer(client);
|
||||
register_on_ssh_read(client);
|
||||
|
||||
tmate_spawn_slave(_session);
|
||||
/* never reached */
|
||||
}
|
||||
|
||||
@ -182,13 +203,13 @@ static void handle_sigchld(void)
|
||||
|
||||
static void handle_sigalrm(void)
|
||||
{
|
||||
tmate_fatal("Connection grace period (%d) passed", SSH_GRACE_PERIOD);
|
||||
tmate_fatal("Connection grace period (%d) passed", TMATE_SSH_GRACE_PERIOD);
|
||||
}
|
||||
|
||||
static void handle_sigsegv(void)
|
||||
{
|
||||
tmate_info("CRASH, printing stack trace");
|
||||
tmate_print_trace();
|
||||
tmate_print_stack_trace();
|
||||
tmate_fatal("CRASHED");
|
||||
}
|
||||
|
||||
@ -208,14 +229,6 @@ static void setup_signals(void)
|
||||
signal(SIGSEGV, signal_handler);
|
||||
}
|
||||
|
||||
static pid_t namespace_fork(void)
|
||||
{
|
||||
/* XXX we are breaking getpid() libc cache. Bad libc. */
|
||||
unsigned long flags;
|
||||
flags = CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWNET;
|
||||
return syscall(SYS_clone, flags | SIGCHLD, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int get_ip(int fd, char *dst, size_t len)
|
||||
{
|
||||
struct sockaddr sa;
|
||||
@ -243,8 +256,6 @@ static int get_ip(int fd, char *dst, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tmate_ssh_client tmate_client;
|
||||
|
||||
static void ssh_log_function(int priority, const char *function,
|
||||
const char *buffer, void *userdata)
|
||||
{
|
||||
@ -281,9 +292,10 @@ static ssh_bind prepare_ssh(const char *keys_dir, int port)
|
||||
return bind;
|
||||
}
|
||||
|
||||
void tmate_ssh_server_main(const char *keys_dir, int port)
|
||||
void tmate_ssh_server_main(struct tmate_session *session,
|
||||
const char *keys_dir, int port)
|
||||
{
|
||||
struct tmate_ssh_client *client = &tmate_client;
|
||||
struct tmate_ssh_client *client = &session->ssh_client;
|
||||
ssh_bind bind;
|
||||
pid_t pid;
|
||||
|
||||
@ -293,6 +305,9 @@ void tmate_ssh_server_main(const char *keys_dir, int port)
|
||||
for (;;) {
|
||||
client->session = ssh_new();
|
||||
client->channel = NULL;
|
||||
client->winsize_pty.ws_col = 80;
|
||||
client->winsize_pty.ws_row = 24;
|
||||
|
||||
if (!client->session)
|
||||
tmate_fatal("Cannot initialize session");
|
||||
|
||||
@ -303,12 +318,8 @@ void tmate_ssh_server_main(const char *keys_dir, int port)
|
||||
client->ip_address, sizeof(client->ip_address)) < 0)
|
||||
tmate_fatal("Error getting IP address from connection");
|
||||
|
||||
if ((pid = namespace_fork()) < 0) {
|
||||
if (getuid() == 0)
|
||||
tmate_fatal("Can't fork in new namespace, are you running a recent kernel?");
|
||||
else
|
||||
tmate_fatal("Can't fork in new namespace, run me with root priviledges");
|
||||
}
|
||||
if ((pid = fork()) < 0)
|
||||
tmate_fatal("Can't fork");
|
||||
|
||||
if (pid) {
|
||||
tmate_info("Child spawned pid=%d, ip=%s",
|
||||
@ -316,8 +327,8 @@ void tmate_ssh_server_main(const char *keys_dir, int port)
|
||||
ssh_free(client->session);
|
||||
} else {
|
||||
ssh_bind_free(bind);
|
||||
tmate_session_token = "init";
|
||||
client_bootstrap(client);
|
||||
session->session_token = "init";
|
||||
client_bootstrap(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
217
tmate.h
217
tmate.h
@ -5,9 +5,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <msgpack.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <event.h>
|
||||
|
||||
#include "tmux.h"
|
||||
struct tmate_session;
|
||||
|
||||
/* log.c */
|
||||
|
||||
extern void init_logging(const char *program_name, bool use_syslog, int log_level);
|
||||
extern void printflike2 tmate_log(int level, const char *msg, ...);
|
||||
@ -22,7 +26,83 @@ extern void printflike2 tmate_log(int level, const char *msg, ...);
|
||||
exit(1); \
|
||||
})
|
||||
|
||||
/* tmate-encoder.c */
|
||||
/* tmate-msgpack.c */
|
||||
|
||||
typedef void tmate_encoder_write_cb(void *userdata, struct evbuffer *buffer);
|
||||
|
||||
struct tmate_encoder {
|
||||
msgpack_packer pk;
|
||||
tmate_encoder_write_cb *ready_callback;
|
||||
void *userdata;
|
||||
struct evbuffer *buffer;
|
||||
struct event ev_buffer;
|
||||
bool ev_active;
|
||||
};
|
||||
|
||||
extern void tmate_encoder_init(struct tmate_encoder *encoder,
|
||||
tmate_encoder_write_cb *callback,
|
||||
void *userdata);
|
||||
|
||||
#define NEW_MSGPACK_API 0
|
||||
|
||||
#if NEW_MSG_PACK
|
||||
#define msgpack_pack_buffer(pk, buf, len) ({ \
|
||||
msgpack_pack_bin(pk, len); \
|
||||
msgpack_pack_bin_body(pk, buf, len); \
|
||||
})
|
||||
|
||||
#define msgpack_pack_string(pk, str) ({ \
|
||||
int __strlen = strlen(str); \
|
||||
msgpack_pack_str(pk, __strlen); \
|
||||
msgpack_pack_str_body(pk, str, __strlen); \
|
||||
})
|
||||
#else
|
||||
/* old msgpack version */
|
||||
#define msgpack_pack_buffer(pk, buf, len) ({ \
|
||||
msgpack_pack_raw(pk, len); \
|
||||
msgpack_pack_raw_body(pk, buf, len); \
|
||||
})
|
||||
|
||||
#define msgpack_pack_string(pk, str) ({ \
|
||||
int __strlen = strlen(str); \
|
||||
msgpack_pack_raw(pk, __strlen); \
|
||||
msgpack_pack_raw_body(pk, str, __strlen); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define _pack(enc, what, ...) msgpack_pack_##what(&(enc)->pk, __VA_ARGS__)
|
||||
|
||||
struct tmate_unpacker;
|
||||
struct tmate_decoder;
|
||||
typedef void tmate_decoder_reader(void *userdata, struct tmate_unpacker *uk);
|
||||
|
||||
struct tmate_decoder {
|
||||
struct msgpack_unpacker unpacker;
|
||||
tmate_decoder_reader *reader;
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
extern void tmate_decoder_init(struct tmate_decoder *decoder, tmate_decoder_reader *reader, void *userdata);
|
||||
extern void tmate_decoder_get_buffer(struct tmate_decoder *decoder, char **buf, size_t *len);
|
||||
extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
|
||||
|
||||
struct tmate_unpacker {
|
||||
msgpack_object *argv;
|
||||
int argc;
|
||||
};
|
||||
|
||||
extern void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj);
|
||||
extern int64_t unpack_int(struct tmate_unpacker *uk);
|
||||
extern void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len);
|
||||
extern char *unpack_string(struct tmate_unpacker *uk);
|
||||
extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested);
|
||||
|
||||
#define unpack_each(nested_uk, tmp_uk, uk) \
|
||||
for (unpack_array(uk, tmp_uk); \
|
||||
(tmp_uk)->argc > 0 && (init_unpacker(nested_uk, (tmp_uk)->argv[0]), 1); \
|
||||
(tmp_uk)->argv++, (tmp_uk)->argc--)
|
||||
|
||||
/* tmate-client-encoder.c */
|
||||
|
||||
#define TMATE_LATEST_VERSION "1.8.10"
|
||||
|
||||
@ -35,14 +115,7 @@ enum tmate_client_commands {
|
||||
TMATE_CLIENT_READY,
|
||||
};
|
||||
|
||||
struct tmate_encoder {
|
||||
struct evbuffer *buffer;
|
||||
struct event ev_readable;
|
||||
struct event ev_notify_timer;
|
||||
msgpack_packer pk;
|
||||
};
|
||||
|
||||
extern void tmate_encoder_init(struct tmate_encoder *encoder);
|
||||
extern void tmate_client_encoder_init(struct tmate_encoder *encoder);
|
||||
|
||||
extern void printflike1 tmate_notify(const char *fmt, ...);
|
||||
extern void printflike2 tmate_notify_later(int timeout, const char *fmt, ...);
|
||||
@ -57,10 +130,11 @@ extern int tmate_should_exec_cmd_locally(const struct cmd_entry *cmd);
|
||||
extern void tmate_send_env(const char *name, const char *value);
|
||||
extern void tmate_send_client_ready(void);
|
||||
|
||||
/* tmate-decoder.c */
|
||||
/* tmate-client-decoder.c */
|
||||
|
||||
#define TMATE_HLIMIT 2000
|
||||
#define TMATE_MAX_MESSAGE_SIZE (16*1024)
|
||||
/* 17 and not 16 because the sender does not takes into account envelope size */
|
||||
#define TMATE_MAX_MESSAGE_SIZE (17*1024)
|
||||
|
||||
extern char *tmate_left_status, *tmate_right_status;
|
||||
|
||||
@ -77,19 +151,23 @@ enum tmate_commands {
|
||||
|
||||
#define TMATE_PANE_ACTIVE 1
|
||||
|
||||
struct tmate_decoder {
|
||||
int protocol;
|
||||
|
||||
struct msgpack_unpacker unpacker;
|
||||
};
|
||||
|
||||
extern void tmate_decoder_init(struct tmate_decoder *decoder);
|
||||
extern void tmate_decoder_get_buffer(struct tmate_decoder *decoder,
|
||||
char **buf, size_t *len);
|
||||
extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
|
||||
extern void tmate_dispatch_daemon_message(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk);
|
||||
|
||||
/* tmate-ssh-client.c */
|
||||
|
||||
extern void tmate_daemon_init(struct tmate_session *session);
|
||||
|
||||
/* tmate-ssh-client-pty.c */
|
||||
|
||||
extern void tmate_ssh_client_pty_init(struct tmate_session *session);
|
||||
extern void tmate_flush_pty(struct tmate_session *session);
|
||||
|
||||
/* tmate-ssh-server.c */
|
||||
|
||||
#define TMATE_SSH_BANNER "tmate"
|
||||
#define TMATE_SSH_KEEPALIVE 60
|
||||
|
||||
#define TMATE_ROLE_SERVER 1
|
||||
#define TMATE_ROLE_CLIENT 2
|
||||
|
||||
@ -98,12 +176,14 @@ struct tmate_ssh_client {
|
||||
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
/*
|
||||
* We need to store the entire callback struct because
|
||||
* libssh stores the userdata within the cb struct...
|
||||
*/
|
||||
struct ssh_channel_callbacks_struct channel_cb;
|
||||
|
||||
int role;
|
||||
|
||||
struct tmate_encoder *encoder;
|
||||
struct tmate_decoder *decoder;
|
||||
|
||||
char *username;
|
||||
char *pubkey;
|
||||
|
||||
@ -111,53 +191,21 @@ struct tmate_ssh_client {
|
||||
|
||||
struct event ev_ssh;
|
||||
struct event ev_keepalive_timer;
|
||||
|
||||
/* only for client-pty */
|
||||
int pty;
|
||||
struct event ev_pty;
|
||||
int readonly;
|
||||
};
|
||||
extern void tmate_ssh_client_init(struct tmate_ssh_client *client,
|
||||
struct tmate_encoder *encoder,
|
||||
struct tmate_decoder *decoder);
|
||||
|
||||
/* tmate-ssh-client-pty.c */
|
||||
|
||||
extern void tmate_ssh_client_pty_init(struct tmate_ssh_client *client);
|
||||
extern void tmate_flush_pty(struct tmate_ssh_client *client);
|
||||
|
||||
/* tmate-ssh-server.c */
|
||||
|
||||
#define TMATE_SSH_BANNER "tmate"
|
||||
#define TMATE_KEEPALIVE 60
|
||||
|
||||
#ifdef TMATE_RECORD_REPLAY
|
||||
extern int tmate_session_log_fd;
|
||||
#endif
|
||||
|
||||
extern struct tmate_ssh_client tmate_client;
|
||||
extern void tmate_start_keepalive_timer(struct tmate_ssh_client *client);
|
||||
extern void tmate_ssh_server_main(const char *keys_dir, int port);
|
||||
extern void tmate_ssh_server_main(struct tmate_session *session,
|
||||
const char *keys_dir, int port);
|
||||
|
||||
/* tmate-slave.c */
|
||||
|
||||
struct tmate_settings {
|
||||
const char *keys_dir;
|
||||
int ssh_port;
|
||||
const char *master_hostname;
|
||||
int master_port;
|
||||
const char *tmate_host;
|
||||
int log_level;
|
||||
bool use_syslog;
|
||||
};
|
||||
extern struct tmate_settings tmate_settings;
|
||||
|
||||
#ifdef DEVENV
|
||||
#define TMATE_SSH_DEFAULT_PORT 2200
|
||||
#else
|
||||
#define TMATE_SSH_DEFAULT_PORT 22
|
||||
#endif
|
||||
|
||||
#define TMATE_SSH_GRACE_PERIOD 60
|
||||
|
||||
#define TMATE_SSH_DEFAULT_KEYS_DIR "keys"
|
||||
|
||||
#define TMATE_DEFAULT_MASTER_HOST NULL
|
||||
@ -167,24 +215,51 @@ extern struct tmate_settings tmate_settings;
|
||||
#define TMATE_WORKDIR "/tmp/tmate"
|
||||
#define TMATE_JAIL_USER "nobody"
|
||||
|
||||
extern int tmate_port;
|
||||
extern struct tmate_encoder *tmate_encoder;
|
||||
extern struct tmate_decoder *tmate_decoder;
|
||||
extern int tmux_socket_fd;
|
||||
extern char *tmate_host;
|
||||
extern const char *tmate_session_token;
|
||||
extern const char *tmate_session_token_ro;
|
||||
struct tmate_settings {
|
||||
const char *keys_dir;
|
||||
int ssh_port;
|
||||
const char *master_hostname;
|
||||
int master_port;
|
||||
const char *tmate_host;
|
||||
int log_level;
|
||||
bool use_syslog;
|
||||
};
|
||||
extern struct tmate_settings *tmate_settings;
|
||||
|
||||
struct tmate_session {
|
||||
struct tmate_ssh_client ssh_client;
|
||||
int tmux_socket_fd;
|
||||
|
||||
/* only for deamon */
|
||||
|
||||
struct tmate_encoder client_encoder;
|
||||
struct tmate_decoder client_decoder;
|
||||
int client_protocol_version;
|
||||
|
||||
struct tmate_encoder master_encoder;
|
||||
struct tmate_decoder master_decoder;
|
||||
|
||||
const char *session_token;
|
||||
const char *session_token_ro;
|
||||
|
||||
struct event ev_notify_timer;
|
||||
|
||||
/* only for client-pty */
|
||||
int pty;
|
||||
struct event ev_pty;
|
||||
bool readonly;
|
||||
};
|
||||
|
||||
extern struct tmate_session *tmate_session;
|
||||
extern void tmate_get_random_bytes(void *buffer, ssize_t len);
|
||||
extern long tmate_get_random_long(void);
|
||||
|
||||
extern void tmate_reopen_logfile(void);
|
||||
extern void tmate_spawn_slave(struct tmate_ssh_client *client);
|
||||
extern void request_server_termination(void);
|
||||
extern void tmate_spawn_slave(struct tmate_session *session);
|
||||
|
||||
/* tmate-debug.c */
|
||||
|
||||
extern void tmate_preload_trace_lib(void);
|
||||
extern void tmate_print_trace(void);
|
||||
extern void tmate_print_stack_trace(void);
|
||||
|
||||
/* tmux-bare.c */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user