From cd3ee3ee4dd5d0120889c065b65d26cc41ec8f71 Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Thu, 7 Nov 2019 08:01:49 -0500 Subject: [PATCH] Refactor code --- Makefile.am | 7 +- tmate-main.c | 322 ++--------------------------------------- tmate-rand.c | 47 ++++++ tmate-ssh-client-pty.c | 134 ++++++++++++++++- tmate-ssh-daemon.c | 106 +++++++++++++- tmate-ssh-exec.c | 17 ++- tmate-ssh-server.c | 6 +- tmate.h | 40 ++++- 8 files changed, 353 insertions(+), 326 deletions(-) create mode 100644 tmate-rand.c diff --git a/Makefile.am b/Makefile.am index c1cb2773..00700122 100644 --- a/Makefile.am +++ b/Makefile.am @@ -175,18 +175,19 @@ dist_tmate_ssh_server_SOURCES = \ signal.c \ status.c \ style.c \ - tmate-debug.c \ tmate-daemon-decoder.c \ tmate-daemon-encoder.c \ tmate-daemon-legacy.c \ - tmate-msgpack.c \ - tmate-websocket.c \ + tmate-debug.c \ tmate-main.c \ + tmate-msgpack.c \ + tmate-rand.c \ tmate-ssh-client-pty.c \ tmate-ssh-daemon.c \ tmate-ssh-exec.c \ tmate-ssh-latency.c \ tmate-ssh-server.c \ + tmate-websocket.c \ tmux.c \ tty-acs.c \ tty-keys.c \ diff --git a/tmate-main.c b/tmate-main.c index eca4a6db..366e1f1f 100644 --- a/tmate-main.c +++ b/tmate-main.c @@ -21,22 +21,12 @@ #include #include "tmate.h" -struct tmate_session _tmate_session, *tmate_session = &_tmate_session; - -extern FILE *log_file; - static char *cmdline; static char *cmdline_end; -static int dev_urandom_fd; - -extern int server_create_socket(void); -extern int client_connect(struct event_base *base, const char *path, int start_server); - -static void tmate_spawn_exec(struct tmate_session *session); struct tmate_settings _tmate_settings = { .keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR, - .authorized_keys_path = NULL, + .authorized_keys_path = NULL, .ssh_port = TMATE_SSH_DEFAULT_PORT, .ssh_port_advertized = -1, .websocket_hostname = NULL, @@ -50,51 +40,6 @@ struct tmate_settings _tmate_settings = { struct tmate_settings *tmate_settings = &_tmate_settings; -void tmate_get_random_bytes(void *buffer, ssize_t len) -{ - if (read(dev_urandom_fd, buffer, len) != len) - tmate_fatal("Cannot read from /dev/urandom"); -} - -long tmate_get_random_long(void) -{ - long val; - tmate_get_random_bytes(&val, sizeof(val)); - return val; -} - -#define RS_BUF_SIZE 256 - -struct random_stream { - char bytes[RS_BUF_SIZE]; - off_t pos; -}; - -static void random_stream_init(struct random_stream *rs) -{ - rs->pos = RS_BUF_SIZE; -} - -static char *random_stream_get(struct random_stream *rs, size_t count) -{ - char *ret; - - if (count > RS_BUF_SIZE) { - tmate_fatal("buffer too small"); - } - - if (rs->pos + count > RS_BUF_SIZE) { - tmate_get_random_bytes(rs->bytes, RS_BUF_SIZE); - rs->pos = 0; - } - - - ret = &rs->bytes[rs->pos]; - rs->pos += count; - return ret; -} - - extern int server_fd; extern void server_send_exit(void); void request_server_termination(void) @@ -214,9 +159,7 @@ int main(int argc, char **argv, char **envp) tmate_preload_trace_lib(); tmate_catch_sigsegv(); - - if ((dev_urandom_fd = open("/dev/urandom", O_RDONLY)) < 0) - tmate_fatal("Cannot open /dev/urandom"); + tmate_init_rand(); if ((mkdir(TMATE_WORKDIR, 0701) < 0 && errno != EEXIST) || (mkdir(TMATE_WORKDIR "/sessions", 0703) < 0 && errno != EEXIST) || @@ -234,41 +177,17 @@ int main(int argc, char **argv, char **envp) return 0; } -static char tmate_token_digits[] = "abcdefghjkmnpqrstuvwxyz" - "ABCDEFGHJKLMNPQRSTUVWXYZ" - "23456789"; - -#define NUM_DIGITS (sizeof(tmate_token_digits) - 1) - -static char *get_random_token(void) -{ - struct random_stream rs; - char *token = xmalloc(TMATE_TOKEN_LEN + 1); - int i; - unsigned char c; - - random_stream_init(&rs); - - for (i = 0; i < TMATE_TOKEN_LEN; i++) { - do { - c = *random_stream_get(&rs, 1); - } while (c >= NUM_DIGITS); - - token[i] = tmate_token_digits[c]; - } - - token[i] = 0; - - return token; -} - -void set_session_token(struct tmate_session *session, - const char *token) +char *get_socket_path(const char *token) { char *path; - session->session_token = xstrdup(token); xasprintf(&path, TMATE_WORKDIR "/sessions/%s", token); - socket_path = path; + return path; +} + +void set_session_token(struct tmate_session *session, const char *token) +{ + session->session_token = xstrdup(token); + socket_path = get_socket_path(token); xasprintf((char **)&session->obfuscated_session_token, "%.4s...", session->session_token); @@ -280,71 +199,7 @@ void set_session_token(struct tmate_session *session, session->ssh_client.ip_address); } -static void create_session_ro_symlink(struct tmate_session *session) -{ - char *tmp, *token, *session_ro_path; - -#ifdef DEVENV - tmp = xstrdup("READONLYTOKENFORDEVENV000"); -#else - tmp = get_random_token(); -#endif - xasprintf(&token, "ro-%s", tmp); - free(tmp); - - session->session_token_ro = token; - - xasprintf(&session_ro_path, TMATE_WORKDIR "/sessions/%s", - session->session_token_ro); - - unlink(session_ro_path); - if (symlink(session->session_token, session_ro_path) < 0) - tmate_fatal("Cannot create read-only symlink"); - free(session_ro_path); -} - -static int validate_token(const char *token) -{ - int len; - int i; - - if (!memcmp("ro-", token, 3)) - token += 3; - - len = strlen(token); - - if (len != TMATE_TOKEN_LEN) - return -1; - - for (i = 0; i < len; i++) { - if (!strchr(tmate_token_digits, token[i])) - return -1; - } - - return 0; -} - -static void random_sleep(void) -{ - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 50000000 + (tmate_get_random_long() % 150000000); - nanosleep(&ts, NULL); -} - -static void ssh_echo(struct tmate_ssh_client *ssh_client, - const char *str) -{ - ssh_channel_write(ssh_client->channel, str, strlen(str)); -} - -#define BAD_TOKEN_ERROR_STR \ -"Invalid session token" "\r\n" - -#define EXPIRED_TOKEN_ERROR_STR \ -"Invalid or expired session token" "\r\n" - -static void close_fds_except(int *fd_to_preserve, int num_fds) +void close_fds_except(int *fd_to_preserve, int num_fds) { int fd, i, preserve; @@ -359,7 +214,7 @@ static void close_fds_except(int *fd_to_preserve, int num_fds) } } -static void jail(void) +void get_in_jail(void) { struct passwd *pw; uid_t uid; @@ -418,161 +273,10 @@ static void jail(void) TMATE_JAIL_USER, uid, gid, TMATE_WORKDIR "/jail"); } -static void setup_ncurse(int fd, const char *name) +void setup_ncurse(int fd, const char *name) { int error; if (setupterm((char *)name, fd, &error) != OK) tmate_fatal("Cannot setup terminal"); } -static void handle_sigterm(__unused int sig) -{ - request_server_termination(); -} - -static void tmate_spawn_daemon(struct tmate_session *session) -{ - struct tmate_ssh_client *client = &session->ssh_client; - char *token; - -#ifdef DEVENV - token = xstrdup("SUPERSECURETOKENFORDEVENV"); -#else - token = get_random_token(); -#endif - - set_session_token(session, token); - free(token); - - tmate_info("Spawning daemon for %s at %s (%s)", - client->username, client->ip_address, client->pubkey); - - 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(session); - - /* - * Needed to initialize the database used in tty-term.c. - * We won't have access to it once in the jail. - */ - setup_ncurse(STDOUT_FILENO, "screen-256color"); - - tmate_daemon_init(session); - - close_fds_except((int[]){session->tmux_socket_fd, - ssh_get_fd(session->ssh_client.session), - log_file ? fileno(log_file) : -1, - session->websocket_fd}, 4); - - jail(); - event_reinit(session->ev_base); - - tmux_server_init(); - signal(SIGTERM, handle_sigterm); - server_start(session->ev_base, -1, NULL); - /* never reached */ -} - -static void tmate_spawn_pty_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; - int argc = 1; - char *token = client->username; - struct stat fstat; - int slave_pty; - int ret; - - if (validate_token(token) < 0) { - ssh_echo(client, BAD_TOKEN_ERROR_STR); - tmate_fatal("Invalid token"); - } - - set_session_token(session, token); - - tmate_info("Spawning pty client for %s (%s)", - client->ip_address, client->pubkey); - - session->tmux_socket_fd = client_connect(session->ev_base, socket_path, 0); - if (session->tmux_socket_fd < 0) { - if (tmate_has_websocket()) { - /* Turn the response into an exec to show a better error */ - client->exec_command = xstrdup("explain-session-not-found"); - tmate_spawn_exec(session); - /* No return */ - } - - random_sleep(); /* for making timing attacks harder */ - ssh_echo(client, EXPIRED_TOKEN_ERROR_STR); - tmate_fatal("Expired token"); - } - - /* - * If we are connecting through a symlink, it means that we are a - * readonly client. - * 1) We mark the client as CLIENT_READONLY on the server - * 2) We prevent any input (aside from the window size) to go through - * to the server. - */ - session->readonly = false; - if (lstat(socket_path, &fstat) < 0) - tmate_fatal("Cannot fstat()"); - if (S_ISLNK(fstat.st_mode)) { - session->readonly = true; - argv = argv_ro; - argc = 2; - } - - if (openpty(&session->pty, &slave_pty, NULL, NULL, NULL) < 0) - tmate_fatal("Cannot allocate pty"); - - dup2(slave_pty, STDIN_FILENO); - dup2(slave_pty, STDOUT_FILENO); - dup2(slave_pty, STDERR_FILENO); - - setup_ncurse(slave_pty, "screen-256color"); - - tmate_client_pty_init(session); - - /* the unused session->websocket_fd will get closed automatically */ - - close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, - session->tmux_socket_fd, - ssh_get_fd(session->ssh_client.session), - session->pty, log_file ? fileno(log_file) : -1}, 7); - jail(); - event_reinit(session->ev_base); - - ret = client_main(session->ev_base, argc, argv, - CLIENT_UTF8 | CLIENT_256COLOURS, NULL); - tmate_flush_pty(session); - exit(ret); -} - -static void tmate_spawn_exec(struct tmate_session *session) -{ - close_fds_except((int[]){ssh_get_fd(session->ssh_client.session), - log_file ? fileno(log_file) : -1, - session->websocket_fd}, 3); - jail(); - event_reinit(session->ev_base); - - tmate_client_exec_init(session); - - if (event_base_dispatch(session->ev_base) < 0) - tmate_fatal("Cannot run event loop"); - exit(0); -} - -void tmate_spawn(struct tmate_session *session) -{ - switch (session->ssh_client.role) { - case TMATE_ROLE_DAEMON: tmate_spawn_daemon(session); break; - case TMATE_ROLE_PTY_CLIENT: tmate_spawn_pty_client(session); break; - case TMATE_ROLE_EXEC: tmate_spawn_exec(session); break; - } -} diff --git a/tmate-rand.c b/tmate-rand.c new file mode 100644 index 00000000..974be3a4 --- /dev/null +++ b/tmate-rand.c @@ -0,0 +1,47 @@ +#include "tmate.h" +#include + +static int dev_urandom_fd; + +void tmate_init_rand(void) +{ + if ((dev_urandom_fd = open("/dev/urandom", O_RDONLY)) < 0) + tmate_fatal("Cannot open /dev/urandom"); +} + +void tmate_get_random_bytes(void *buffer, ssize_t len) +{ + if (read(dev_urandom_fd, buffer, len) != len) + tmate_fatal("Cannot read from /dev/urandom"); +} + +long tmate_get_random_long(void) +{ + long val; + tmate_get_random_bytes(&val, sizeof(val)); + return val; +} + +void random_stream_init(struct random_stream *rs) +{ + rs->pos = RS_BUF_SIZE; +} + +char *random_stream_get(struct random_stream *rs, size_t count) +{ + char *ret; + + if (count > RS_BUF_SIZE) { + tmate_fatal("buffer too small"); + } + + if (rs->pos + count > RS_BUF_SIZE) { + tmate_get_random_bytes(rs->bytes, RS_BUF_SIZE); + rs->pos = 0; + } + + + ret = &rs->bytes[rs->pos]; + rs->pos += count; + return ret; +} diff --git a/tmate-ssh-client-pty.c b/tmate-ssh-client-pty.c index 6e461d77..80df5403 100644 --- a/tmate-ssh-client-pty.c +++ b/tmate-ssh-client-pty.c @@ -1,11 +1,10 @@ #include #include #include +#include #include #include "tmate.h" -extern void client_signal(int sig); - static int on_ssh_channel_read(__unused ssh_session _session, __unused ssh_channel channel, void *_data, uint32_t total_len, @@ -85,13 +84,13 @@ static void __on_pty_event(__unused evutil_socket_t fd, __unused short what, voi on_pty_event(arg); } -void tmate_flush_pty(struct tmate_session *session) +static void tmate_flush_pty(struct tmate_session *session) { on_pty_event(session); close(session->pty); } -void tmate_client_pty_init(struct tmate_session *session) +static void tmate_client_pty_init(struct tmate_session *session) { struct tmate_ssh_client *client = &session->ssh_client; @@ -111,3 +110,130 @@ void tmate_client_pty_init(struct tmate_session *session) EV_READ | EV_PERSIST, __on_pty_event, session); event_add(&session->ev_pty, NULL); } + +static void random_sleep(void) +{ + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 50000000 + (tmate_get_random_long() % 150000000); + nanosleep(&ts, NULL); +} + +#define BAD_TOKEN_ERROR_STR \ +"Invalid session token" "\r\n" + +#define EXPIRED_TOKEN_ERROR_STR \ +"Invalid or expired session token" "\r\n" + +static void ssh_echo(struct tmate_ssh_client *ssh_client, + const char *str) +{ + ssh_channel_write(ssh_client->channel, str, strlen(str)); +} + + +/* + * Session tokens are filesystem sensitive, + * so we must be very careful with / and . + */ +static char valid_digits[] = "abcdefghjklmnopqrstuvwxyz" + "ABCDEFGHJKLMNOPQRSTUVWXYZ" + "0123456789-_"; + +int tmate_validated_session_token(const char *token) +{ + int len; + int i; + + if (!memcmp("ro-", token, 3)) + token += 3; + + len = strlen(token); + + if (len != TMATE_TOKEN_LEN) + return -1; + + for (i = 0; i < len; i++) { + if (!strchr(valid_digits, token[i])) + return -1; + } + + return 0; +} + +void tmate_spawn_pty_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; + int argc = 1; + char *token = client->username; + struct stat fstat; + int slave_pty; + int ret; + + if (tmate_validated_session_token(token) < 0) { + ssh_echo(client, BAD_TOKEN_ERROR_STR); + tmate_fatal("Invalid token"); + } + + set_session_token(session, token); + + tmate_info("Spawning pty client for %s (%s)", + client->ip_address, client->pubkey); + + session->tmux_socket_fd = client_connect(session->ev_base, socket_path, 0); + if (session->tmux_socket_fd < 0) { + if (tmate_has_websocket()) { + /* Turn the response into an exec to show a better error */ + client->exec_command = xstrdup("explain-session-not-found"); + tmate_spawn_exec(session); + /* No return */ + } + + random_sleep(); /* for making timing attacks harder */ + ssh_echo(client, EXPIRED_TOKEN_ERROR_STR); + tmate_fatal("Expired token"); + } + + /* + * If we are connecting through a symlink, it means that we are a + * readonly client. + * 1) We mark the client as CLIENT_READONLY on the server + * 2) We prevent any input (aside from the window size) to go through + * to the server. + */ + session->readonly = false; + if (lstat(socket_path, &fstat) < 0) + tmate_fatal("Cannot fstat()"); + if (S_ISLNK(fstat.st_mode)) { + session->readonly = true; + argv = argv_ro; + argc = 2; + } + + if (openpty(&session->pty, &slave_pty, NULL, NULL, NULL) < 0) + tmate_fatal("Cannot allocate pty"); + + dup2(slave_pty, STDIN_FILENO); + dup2(slave_pty, STDOUT_FILENO); + dup2(slave_pty, STDERR_FILENO); + + setup_ncurse(slave_pty, "screen-256color"); + + tmate_client_pty_init(session); + + /* the unused session->websocket_fd will get closed automatically */ + close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, + session->tmux_socket_fd, + ssh_get_fd(session->ssh_client.session), + session->pty, log_file ? fileno(log_file) : -1}, 7); + get_in_jail(); + event_reinit(session->ev_base); + + ret = client_main(session->ev_base, argc, argv, + CLIENT_UTF8 | CLIENT_256COLOURS, NULL); + tmate_flush_pty(session); + exit(ret); +} diff --git a/tmate-ssh-daemon.c b/tmate-ssh-daemon.c index 505e0fd6..5cde64a3 100644 --- a/tmate-ssh-daemon.c +++ b/tmate-ssh-daemon.c @@ -1,6 +1,8 @@ #include "tmate.h" #include +struct tmate_session _tmate_session, *tmate_session = &_tmate_session; + static void on_daemon_decoder_read(void *userdata, struct tmate_unpacker *uk) { struct tmate_session *session = userdata; @@ -66,7 +68,7 @@ static void on_daemon_encoder_write(void *userdata, struct evbuffer *buffer) } } -void tmate_daemon_init(struct tmate_session *session) +static void tmate_daemon_init(struct tmate_session *session) { struct tmate_ssh_client *client = &session->ssh_client; @@ -81,3 +83,105 @@ void tmate_daemon_init(struct tmate_session *session) tmate_init_websocket(session, NULL); } + +static void handle_sigterm(__unused int sig) +{ + request_server_termination(); +} + +/* We skip letters that are hard to distinguish when reading */ +static char rand_tmate_token_digits[] = "abcdefghjkmnpqrstuvwxyz" + "ABCDEFGHJKLMNPQRSTUVWXYZ" + "23456789"; + +#define NUM_DIGITS (sizeof(rand_tmate_token_digits) - 1) + +static char *get_random_token(void) +{ + struct random_stream rs; + char *token = xmalloc(TMATE_TOKEN_LEN + 1); + int i; + unsigned char c; + + random_stream_init(&rs); + + for (i = 0; i < TMATE_TOKEN_LEN; i++) { + do { + c = *random_stream_get(&rs, 1); + } while (c >= NUM_DIGITS); + + token[i] = rand_tmate_token_digits[c]; + } + + token[i] = 0; + + return token; +} + +static void create_session_ro_symlink(struct tmate_session *session) +{ + char *tmp, *token, *session_ro_path; + +#ifdef DEVENV + tmp = xstrdup("READONLYTOKENFORDEVENV000"); +#else + tmp = get_random_token(); +#endif + xasprintf(&token, "ro-%s", tmp); + free(tmp); + + session->session_token_ro = token; + + xasprintf(&session_ro_path, TMATE_WORKDIR "/sessions/%s", + session->session_token_ro); + + unlink(session_ro_path); + if (symlink(session->session_token, session_ro_path) < 0) + tmate_fatal("Cannot create read-only symlink"); + free(session_ro_path); +} + +void tmate_spawn_daemon(struct tmate_session *session) +{ + struct tmate_ssh_client *client = &session->ssh_client; + char *token; + +#ifdef DEVENV + token = xstrdup("SUPERSECURETOKENFORDEVENV"); +#else + token = get_random_token(); +#endif + + set_session_token(session, token); + free(token); + + tmate_info("Spawning daemon for %s at %s (%s)", + client->username, client->ip_address, client->pubkey); + + 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(session); + + /* + * Needed to initialize the database used in tty-term.c. + * We won't have access to it once in the jail. + */ + setup_ncurse(STDOUT_FILENO, "screen-256color"); + + tmate_daemon_init(session); + + close_fds_except((int[]){session->tmux_socket_fd, + ssh_get_fd(session->ssh_client.session), + log_file ? fileno(log_file) : -1, + session->websocket_fd}, 4); + + get_in_jail(); + event_reinit(session->ev_base); + + tmux_server_init(); + signal(SIGTERM, handle_sigterm); + server_start(session->ev_base, -1, NULL); + /* never reached */ +} diff --git a/tmate-ssh-exec.c b/tmate-ssh-exec.c index fc425735..fff384fc 100644 --- a/tmate-ssh-exec.c +++ b/tmate-ssh-exec.c @@ -23,7 +23,7 @@ static void on_websocket_error(struct tmate_session *session, __unused short eve tmate_dump_exec_response(session, 1, "Internal Error\r\n"); } -void tmate_client_exec_init(struct tmate_session *session) +static void tmate_client_exec_init(struct tmate_session *session) { struct tmate_ssh_client *client = &session->ssh_client; @@ -35,3 +35,18 @@ void tmate_client_exec_init(struct tmate_session *session) tmate_websocket_exec(session, client->exec_command); } + +void tmate_spawn_exec(struct tmate_session *session) +{ + close_fds_except((int[]){ssh_get_fd(session->ssh_client.session), + log_file ? fileno(log_file) : -1, + session->websocket_fd}, 3); + get_in_jail(); + event_reinit(session->ev_base); + + tmate_client_exec_init(session); + + if (event_base_dispatch(session->ev_base) < 0) + tmate_fatal("Cannot run event loop"); + exit(0); +} diff --git a/tmate-ssh-server.c b/tmate-ssh-server.c index 205744f0..6d00f527 100644 --- a/tmate-ssh-server.c +++ b/tmate-ssh-server.c @@ -304,7 +304,11 @@ static void client_bootstrap(struct tmate_session *_session) start_keepalive_timer(client, TMATE_SSH_KEEPALIVE_SEC * 1000); register_on_ssh_read(client); - tmate_spawn(_session); + switch (client->role) { + case TMATE_ROLE_DAEMON: tmate_spawn_daemon(_session); break; + case TMATE_ROLE_PTY_CLIENT: tmate_spawn_pty_client(_session); break; + case TMATE_ROLE_EXEC: tmate_spawn_exec(_session); break; + } /* never reached */ } diff --git a/tmate.h b/tmate.h index fbcc9ebe..c3ca0ef2 100644 --- a/tmate.h +++ b/tmate.h @@ -127,18 +127,16 @@ extern void tmate_dispatch_daemon_message(struct tmate_session *session, #define TMATE_KEYFRAME_INTERVAL_SEC 10 #define TMATE_KEYFRAME_MAX_SIZE 1024*1024 -extern void tmate_daemon_init(struct tmate_session *session); +extern void tmate_spawn_daemon(struct tmate_session *session); /* tmate-ssh-exec.c */ - +extern void tmate_spawn_exec(struct tmate_session *session); 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 */ - -extern void tmate_client_pty_init(struct tmate_session *session); -extern void tmate_flush_pty(struct tmate_session *session); +extern void tmate_spawn_pty_client(struct tmate_session *session); +extern int tmate_validated_session_token(const char *token); /* tmate-ssh-server.c */ @@ -257,9 +255,27 @@ 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 request_server_termination(void); -extern void tmate_spawn(struct tmate_session *session); +extern char *get_socket_path(const char *_token); extern void set_session_token(struct tmate_session *session, const char *token); +extern void close_fds_except(int *fd_to_preserve, int num_fds); +extern void get_in_jail(void); + +/* tmate-rand.c */ +#define RS_BUF_SIZE 256 + +struct random_stream { + char bytes[RS_BUF_SIZE]; + off_t pos; +}; + +extern void tmate_init_rand(void); +extern void tmate_get_random_bytes(void *buffer, ssize_t len); +extern long tmate_get_random_long(void); +extern void random_stream_init(struct random_stream *rs); +extern char *random_stream_get(struct random_stream *rs, size_t count); +extern void setup_ncurse(int fd, const char *name); + /* tmate-websocket.c */ extern void tmate_websocket_exec(struct tmate_session *session, const char *command); @@ -288,4 +304,14 @@ extern void tmate_catch_sigsegv(void); extern void tmux_server_init(void); +/* server.c */ +extern int server_create_socket(void); + +/* log.c */ +extern FILE *log_file; + +/* client.c */ +extern void client_signal(int sig); +extern int client_connect(struct event_base *base, const char *path, int start_server); + #endif