1 #ifndef TMATE_H
2 #define TMATE_H
3
4 #include <sys/types.h>
5 #include <msgpack.h>
6 #include <libssh/libssh.h>
7 #include <libssh/callbacks.h>
8 #include <event.h>
9 #include <time.h>
10
11 #include "tmux.h"
12 struct tmate_session;
13
14 /* log.c */
15
16 #define tmate_debug(...) log_emit(LOG_DEBUG, __VA_ARGS__)
17 #define tmate_info(...) log_emit(LOG_INFO, __VA_ARGS__)
18 #define tmate_fatal(...) fatalx( __VA_ARGS__)
19 #define tmate_fatal_quiet(...) ({tmate_debug(__VA_ARGS__); exit(1);})
20
21 /* tmate-auth-keys.c */
22 extern void tmate_hook_set_option_auth(const char *name, const char *val);
23 extern bool tmate_allow_auth(const char *pubkey);
24 extern bool would_tmate_session_allow_auth(const char *token, const char *pubkey);
25 extern int get_num_authorized_keys(ssh_key *keys);
26
27 /* tmate-msgpack.c */
28
29 typedef void tmate_encoder_write_cb(void *userdata, struct evbuffer *buffer);
30
31 struct tmate_encoder {
32 msgpack_packer pk;
33 int mpac_version;
34 tmate_encoder_write_cb *ready_callback;
35 void *userdata;
36 struct evbuffer *buffer;
37 struct event ev_buffer;
38 bool ev_active;
39 };
40
41 extern void tmate_encoder_init(struct tmate_encoder *encoder,
42 tmate_encoder_write_cb *callback,
43 void *userdata);
44
45 /* These functions deal with dual v4/v5 support through mpac_version */
46 extern void msgpack_pack_string(msgpack_packer *pk, const char *str);
47 extern void msgpack_pack_boolean(msgpack_packer *pk, bool value);
48 extern int _msgpack_pack_object(msgpack_packer *pk, msgpack_object d);
49 #define msgpack_pack_object _msgpack_pack_object
50
51 #define _pack(enc, what, ...) msgpack_pack_##what(&(enc)->pk, ##__VA_ARGS__)
52
53 struct tmate_unpacker;
54 struct tmate_decoder;
55 typedef void tmate_decoder_reader(void *userdata, struct tmate_unpacker *uk);
56
57 struct tmate_decoder {
58 struct msgpack_unpacker unpacker;
59 tmate_decoder_reader *reader;
60 void *userdata;
61 };
62
63 extern void tmate_decoder_init(struct tmate_decoder *decoder, tmate_decoder_reader *reader, void *userdata);
64 extern void tmate_decoder_get_buffer(struct tmate_decoder *decoder, char **buf, size_t *len);
65 extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
66
67 struct tmate_unpacker {
68 int argc;
69 msgpack_object *argv;
70 };
71
72 extern void init_unpacker(struct tmate_unpacker *uk, msgpack_object obj);
73 extern void tmate_decoder_error(void);
74 extern int64_t unpack_int(struct tmate_unpacker *uk);
75 extern bool unpack_bool(struct tmate_unpacker *uk);
76 extern void unpack_buffer(struct tmate_unpacker *uk, const char **buf, size_t *len);
77 extern char *unpack_string(struct tmate_unpacker *uk);
78 extern void unpack_array(struct tmate_unpacker *uk, struct tmate_unpacker *nested);
79 extern msgpack_object_type unpack_peek_type(struct tmate_unpacker *uk);
80
81 #define unpack_each(nested_uk, tmp_uk, uk) \
82 for (unpack_array(uk, tmp_uk); \
83 (tmp_uk)->argc > 0 && (init_unpacker(nested_uk, (tmp_uk)->argv[0]), 1); \
84 (tmp_uk)->argv++, (tmp_uk)->argc--)
85
86 /* tmate-daemon-encoder.c */
87
88 extern void printflike(1, 2) tmate_notify(const char *fmt, ...);
89 extern void printflike(2, 3) tmate_notify_later(int timeout, const char *fmt, ...);
90
91 extern void tmate_client_resize(u_int sx, u_int sy);
92 extern void tmate_client_legacy_pane_key(int pane_id, int key);
93 extern void tmate_client_pane_key(int pane_id, key_code key);
94 extern void tmate_client_cmd_str(int client_id, const char *cmd);
95 extern void tmate_client_cmd_args(int client_id, int argc, const char **argv);
96 extern void tmate_client_cmd(int client_id, struct cmd *cmd);
97 extern void tmate_client_set_active_pane(int client_id, int win_idx, int pane_id);
98 extern int tmate_should_exec_cmd_locally(const struct cmd_entry *cmd);
99 extern void tmate_set_env(const char *name, const char *value);
100 extern void tmate_send_client_ready(void);
101 extern void tmate_send_mc_obj(msgpack_object *obj);
102
103 /* tmate-daemon-legacy.c */
104
105 extern void tmate_translate_legacy_key(int pane_id, key_code key);
106
107 /* tmate-daemon-decoder.c */
108
109 #define TMATE_HLIMIT 2000
110 #define TMATE_PANE_ACTIVE 1
111
112 extern char *tmate_left_status, *tmate_right_status;
113 extern void tmate_dispatch_daemon_message(struct tmate_session *session,
114 struct tmate_unpacker *uk);
115
116 /* tmate-ssh-daemon.c */
117
118 #define TMATE_KEYFRAME_INTERVAL_SEC 10
119 #define TMATE_KEYFRAME_MAX_SIZE 1024*1024
120
121 extern void tmate_spawn_daemon(struct tmate_session *session);
122 extern void tmate_hook_set_option(const char *name, const char *val);
123
124 /* tmate-ssh-exec.c */
125 extern void tmate_spawn_exec(struct tmate_session *session);
126 extern void tmate_dump_exec_response(struct tmate_session *session,
127 int exit_code, const char *message);
128
129 /* tmate-ssh-client-pty.c */
130 extern void tmate_spawn_pty_client(struct tmate_session *session);
131 extern int tmate_validate_session_token(const char *token);
132
133 /* tmate-ssh-server.c */
134
135 #define TMATE_SSH_BANNER "tmate"
136 #define TMATE_SSH_KEEPALIVE_SEC 300
137
138 #define TMATE_ROLE_DAEMON 1
139 #define TMATE_ROLE_PTY_CLIENT 2
140 #define TMATE_ROLE_EXEC 3
141
142 struct tmate_ssh_client;
143 typedef void ssh_client_latency_cb(void *userdata, int latency_ms);
144 extern char *get_ssh_conn_string(const char *session_token);
145 extern void start_keepalive_timer(struct tmate_ssh_client *client, int timeout_ms);
146
147 struct tmate_ssh_client {
148 char ip_address[64];
149
150 ssh_session session;
151 ssh_channel channel;
152 /*
153 * We need to store the entire callback struct because
154 * libssh stores the userdata within the cb struct...
155 */
156 struct ssh_channel_callbacks_struct channel_cb;
157
158 int role;
159
160 char *username;
161 char *pubkey;
162
163 char *exec_command;
164
165 struct winsize winsize_pty;
166
167 struct event ev_ssh;
168
169 struct event ev_keepalive_timer;
170 int keepalive_interval_ms;
171 };
172
173 extern void tmate_ssh_server_main(struct tmate_session *session,
174 const char *keys_dir, const char *bind_addr, int port);
175
176 /* tmate-main.c */
177
178 #ifdef DEVENV
179 #define TMATE_SSH_DEFAULT_PORT 2200
180 #else
181 #define TMATE_SSH_DEFAULT_PORT 22
182 #endif
183
184 #define TMATE_SSH_GRACE_PERIOD 20
185
186 #define TMATE_SSH_DEFAULT_KEYS_DIR "keys"
187
188 #define TMATE_DEFAULT_WEBSOCKET_PORT 4002
189
190 #define TMATE_TOKEN_LEN 25
191 #define TMATE_WORKDIR "/tmp/tmate"
192 #define TMATE_JAIL_USER "nobody"
193
194 struct tmate_settings {
195 const char *keys_dir;
196 const char *authorized_keys_path;
197 int ssh_port;
198 int ssh_port_advertized;
199 const char *websocket_hostname;
200 int websocket_port;
201 const char *tmate_host;
202 const char *bind_addr;
203 int log_level;
204 bool use_proxy_protocol;
205 };
206 extern struct tmate_settings *tmate_settings;
207
208 typedef void on_websocket_error_cb(struct tmate_session *session, short events);
209
210 struct tmate_session {
211 struct event_base *ev_base;
212 struct tmate_ssh_client ssh_client;
213 int tmux_socket_fd;
214
215 /* only for role deamon */
216 ssh_key *authorized_keys; /* array with NULL as last element */
217
218 const char *session_token;
219 const char *session_token_ro;
220 const char *obfuscated_session_token; /* for logging purposes */
221
222 struct tmate_encoder daemon_encoder;
223 struct tmate_decoder daemon_decoder;
224 const char *client_version;
225 int client_protocol_version;
226 struct event ev_notify_timer;
227 bool fin_received;
228
229 int websocket_fd;
230 struct bufferevent *bev_websocket;
231 struct tmate_encoder websocket_encoder;
232 struct tmate_decoder websocket_decoder;
233 u_int websocket_sx, websocket_sy;
234 on_websocket_error_cb *on_websocket_error;
235
236 /* only for role client-pty */
237 int pty;
238 struct event ev_pty;
239 bool readonly;
240
241 /* only for role-exec */
242 bool response_received;
243 bool response_status;
244 const char *response_message;
245 };
246
247 extern struct tmate_session *tmate_session;
248 extern void tmate_get_random_bytes(void *buffer, ssize_t len);
249 extern long tmate_get_random_long(void);
250 extern void request_server_termination(void);
251 extern char *get_socket_path(const char *_token);
252 extern void set_session_token(struct tmate_session *session, const char *token);
253
254 extern void close_fds_except(int *fd_to_preserve, int num_fds);
255 extern void get_in_jail(void);
256
257 /* tmate-rand.c */
258 #define RS_BUF_SIZE 256
259
260 struct random_stream {
261 char bytes[RS_BUF_SIZE];
262 off_t pos;
263 };
264
265 extern void tmate_init_rand(void);
266 extern void tmate_get_random_bytes(void *buffer, ssize_t len);
267 extern long tmate_get_random_long(void);
268 extern void random_stream_init(struct random_stream *rs);
269 extern char *random_stream_get(struct random_stream *rs, size_t count);
270 extern void setup_ncurse(int fd, const char *name);
271
272 /* tmate-websocket.c */
273
274 extern void tmate_websocket_exec(struct tmate_session *session, const char *command);
275 extern void tmate_notify_client_join(struct tmate_session *s, struct client *c);
276 extern void tmate_notify_client_left(struct tmate_session *s, struct client *c);
277
278 extern void tmate_send_websocket_daemon_msg(struct tmate_session *session,
279 struct tmate_unpacker *uk);
280 extern void tmate_send_websocket_header(struct tmate_session *session);
281 extern void tmate_init_websocket(struct tmate_session *session,
282 on_websocket_error_cb on_websocket_error);
283
284 extern int tmate_connect_to_websocket(void);
tmate_has_websocket(void)285 static inline bool tmate_has_websocket(void)
286 {
287 return !!tmate_settings->websocket_hostname;
288 }
289
290 /* tmate-debug.c */
291
292 extern void tmate_preload_trace_lib(void);
293 extern void tmate_print_stack_trace(void);
294 extern void tmate_catch_sigsegv(void);
295
296 /* tmux.c */
297
298 extern void tmux_server_init(void);
299
300 /* server.c */
301 extern int server_create_socket(void);
302
303 /* log.c */
304 extern FILE *log_file;
305
306 /* client.c */
307 extern void client_signal(int sig);
308 extern int client_connect(struct event_base *base, const char *path, int start_server);
309
310 #endif
311