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