mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2025-03-14 20:32:46 +00:00

Add an option to the server to force clients to always set an authorized_keys file. Without it it is all too easy to forget and leave the connexions accessible to anyone with the session name. Co-authored-by: Jonathan Sambrook <jonathan.sambrook@codethink.co.uk>
313 lines
9.2 KiB
C
313 lines
9.2 KiB
C
#ifndef TMATE_H
|
|
#define TMATE_H
|
|
|
|
#include <sys/types.h>
|
|
#include <msgpack.h>
|
|
#include <libssh/libssh.h>
|
|
#include <libssh/callbacks.h>
|
|
#include <event.h>
|
|
#include <time.h>
|
|
|
|
#include "tmux.h"
|
|
struct tmate_session;
|
|
|
|
/* log.c */
|
|
|
|
#define tmate_debug(...) log_emit(LOG_DEBUG, __VA_ARGS__)
|
|
#define tmate_info(...) log_emit(LOG_INFO, __VA_ARGS__)
|
|
#define tmate_fatal(...) fatalx( __VA_ARGS__)
|
|
#define tmate_fatal_quiet(...) ({tmate_debug(__VA_ARGS__); exit(1);})
|
|
|
|
/* tmate-auth-keys.c */
|
|
extern void tmate_hook_set_option_auth(const char *name, const char *val);
|
|
extern bool tmate_allow_auth(const char *pubkey);
|
|
extern bool would_tmate_session_allow_auth(const char *token, const char *pubkey);
|
|
extern int get_num_authorized_keys(ssh_key *keys);
|
|
|
|
/* tmate-msgpack.c */
|
|
|
|
typedef void tmate_encoder_write_cb(void *userdata, struct evbuffer *buffer);
|
|
|
|
struct tmate_encoder {
|
|
msgpack_packer pk;
|
|
int mpac_version;
|
|
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);
|
|
|
|
/* 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_boolean(msgpack_packer *pk, bool value);
|
|
extern int _msgpack_pack_object(msgpack_packer *pk, msgpack_object d);
|
|
#define msgpack_pack_object _msgpack_pack_object
|
|
|
|
#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 {
|
|
int argc;
|
|
msgpack_object *argv;
|
|
};
|
|
|
|
extern void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj);
|
|
extern void tmate_decoder_error(void);
|
|
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 char *unpack_string(struct tmate_unpacker *uk);
|
|
extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested);
|
|
extern msgpack_object_type unpack_peek_type(struct tmate_unpacker *uk);
|
|
|
|
#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-daemon-encoder.c */
|
|
|
|
extern void printflike(1, 2) tmate_notify(const char *fmt, ...);
|
|
extern void printflike(2, 3) tmate_notify_later(int timeout, const char *fmt, ...);
|
|
|
|
extern void tmate_client_resize(u_int sx, u_int sy);
|
|
extern void tmate_client_legacy_pane_key(int pane_id, int key);
|
|
extern void tmate_client_pane_key(int pane_id, key_code key);
|
|
extern void tmate_client_cmd_str(int client_id, const char *cmd);
|
|
extern void tmate_client_cmd_args(int client_id, int argc, const char **argv);
|
|
extern void tmate_client_cmd(int client_id, struct cmd *cmd);
|
|
extern void tmate_client_set_active_pane(int client_id, int win_idx, int pane_id);
|
|
extern int tmate_should_exec_cmd_locally(const struct cmd_entry *cmd);
|
|
extern void tmate_set_env(const char *name, const char *value);
|
|
extern void tmate_send_client_ready(void);
|
|
extern void tmate_send_mc_obj(msgpack_object *obj);
|
|
|
|
/* tmate-daemon-legacy.c */
|
|
|
|
extern void tmate_translate_legacy_key(int pane_id, key_code key);
|
|
|
|
/* tmate-daemon-decoder.c */
|
|
|
|
#define TMATE_HLIMIT 2000
|
|
#define TMATE_PANE_ACTIVE 1
|
|
#define TMATE_MAX_MESSAGE_SIZE (17*1024)
|
|
#define TMATE_MAX_PANES 1000
|
|
|
|
extern char *tmate_left_status, *tmate_right_status;
|
|
extern void tmate_dispatch_daemon_message(struct tmate_session *session,
|
|
struct tmate_unpacker *uk);
|
|
|
|
/* tmate-ssh-daemon.c */
|
|
|
|
#define TMATE_KEYFRAME_INTERVAL_SEC 10
|
|
#define TMATE_KEYFRAME_MAX_SIZE 1024*1024
|
|
|
|
extern void tmate_spawn_daemon(struct tmate_session *session);
|
|
extern void tmate_hook_set_option(const char *name, const char *val);
|
|
|
|
/* 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);
|
|
|
|
/* tmate-ssh-client-pty.c */
|
|
extern void tmate_spawn_pty_client(struct tmate_session *session);
|
|
extern int tmate_validate_session_token(const char *token);
|
|
|
|
/* tmate-ssh-server.c */
|
|
|
|
#define TMATE_SSH_BANNER "tmate"
|
|
#define TMATE_SSH_KEEPALIVE_SEC 300
|
|
|
|
#define TMATE_ROLE_DAEMON 1
|
|
#define TMATE_ROLE_PTY_CLIENT 2
|
|
#define TMATE_ROLE_EXEC 3
|
|
|
|
struct tmate_ssh_client;
|
|
typedef void ssh_client_latency_cb(void *userdata, int latency_ms);
|
|
extern char *get_ssh_conn_string(const char *session_token);
|
|
extern void start_keepalive_timer(struct tmate_ssh_client *client, int timeout_ms);
|
|
|
|
struct tmate_ssh_client {
|
|
char ip_address[64];
|
|
|
|
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;
|
|
|
|
char *username;
|
|
char *pubkey;
|
|
|
|
char *exec_command;
|
|
|
|
struct winsize winsize_pty;
|
|
|
|
struct event ev_ssh;
|
|
|
|
struct event ev_keepalive_timer;
|
|
int keepalive_interval_ms;
|
|
};
|
|
|
|
extern void tmate_ssh_server_main(struct tmate_session *session,
|
|
const char *keys_dir, const char *bind_addr, int port);
|
|
|
|
/* tmate-main.c */
|
|
|
|
#ifdef DEVENV
|
|
#define TMATE_SSH_DEFAULT_PORT 2200
|
|
#else
|
|
#define TMATE_SSH_DEFAULT_PORT 22
|
|
#endif
|
|
|
|
#define TMATE_SSH_GRACE_PERIOD 20
|
|
|
|
#define TMATE_SSH_DEFAULT_KEYS_DIR "keys"
|
|
|
|
#define TMATE_DEFAULT_WEBSOCKET_PORT 4002
|
|
|
|
#define TMATE_TOKEN_LEN 25
|
|
#define TMATE_WORKDIR "/tmp/tmate"
|
|
#define TMATE_JAIL_USER "nobody"
|
|
|
|
struct tmate_settings {
|
|
const char *keys_dir;
|
|
const char *authorized_keys_path;
|
|
bool authorized_keys_only;
|
|
int ssh_port;
|
|
int ssh_port_advertized;
|
|
const char *websocket_hostname;
|
|
int websocket_port;
|
|
const char *tmate_host;
|
|
const char *bind_addr;
|
|
int log_level;
|
|
bool use_proxy_protocol;
|
|
};
|
|
extern struct tmate_settings *tmate_settings;
|
|
|
|
typedef void on_websocket_error_cb(struct tmate_session *session, short events);
|
|
|
|
struct tmate_session {
|
|
struct event_base *ev_base;
|
|
struct tmate_ssh_client ssh_client;
|
|
int tmux_socket_fd;
|
|
|
|
/* only for role deamon */
|
|
ssh_key *authorized_keys; /* array with NULL as last element */
|
|
|
|
const char *session_token;
|
|
const char *session_token_ro;
|
|
const char *obfuscated_session_token; /* for logging purposes */
|
|
|
|
struct tmate_encoder daemon_encoder;
|
|
struct tmate_decoder daemon_decoder;
|
|
const char *client_version;
|
|
int client_protocol_version;
|
|
struct event ev_notify_timer;
|
|
bool fin_received;
|
|
|
|
int websocket_fd;
|
|
struct bufferevent *bev_websocket;
|
|
struct tmate_encoder websocket_encoder;
|
|
struct tmate_decoder websocket_decoder;
|
|
u_int websocket_sx, websocket_sy;
|
|
on_websocket_error_cb *on_websocket_error;
|
|
|
|
/* only for role client-pty */
|
|
int pty;
|
|
struct event ev_pty;
|
|
bool readonly;
|
|
|
|
/* only for role-exec */
|
|
bool response_received;
|
|
bool response_status;
|
|
const char *response_message;
|
|
};
|
|
|
|
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 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);
|
|
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_websocket_daemon_msg(struct tmate_session *session,
|
|
struct tmate_unpacker *uk);
|
|
extern void tmate_send_websocket_header(struct tmate_session *session);
|
|
extern void tmate_init_websocket(struct tmate_session *session,
|
|
on_websocket_error_cb on_websocket_error);
|
|
|
|
extern int tmate_connect_to_websocket(void);
|
|
static inline bool tmate_has_websocket(void)
|
|
{
|
|
return !!tmate_settings->websocket_hostname;
|
|
}
|
|
|
|
/* tmate-debug.c */
|
|
|
|
extern void tmate_preload_trace_lib(void);
|
|
extern void tmate_print_stack_trace(void);
|
|
extern void tmate_catch_sigsegv(void);
|
|
|
|
/* tmux.c */
|
|
|
|
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
|