mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Readonly support on the client side
For now, the client can "tmate show-messages" to get it
This commit is contained in:
parent
d02e97c206
commit
6b31869600
@ -21,6 +21,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
#include "tmate.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach existing session to the current terminal.
|
* Attach existing session to the current terminal.
|
||||||
|
@ -60,6 +60,10 @@ cmd_switch_client_key_binding(struct cmd *self, int key)
|
|||||||
enum cmd_retval
|
enum cmd_retval
|
||||||
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
|
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||||
{
|
{
|
||||||
|
#ifdef TMATE_SLAVE
|
||||||
|
cmdq_error(cmdq, "client switch is not supported");
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
#else
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
@ -111,4 +115,5 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
4
resize.c
4
resize.c
@ -61,6 +61,10 @@ recalculate_sizes(void)
|
|||||||
c = ARRAY_ITEM(&clients, j);
|
c = ARRAY_ITEM(&clients, j);
|
||||||
if (c == NULL || c->flags & CLIENT_SUSPENDED)
|
if (c == NULL || c->flags & CLIENT_SUSPENDED)
|
||||||
continue;
|
continue;
|
||||||
|
#ifdef TMATE_SLAVE
|
||||||
|
if (c->flags & CLIENT_READONLY)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
if (c->session == s) {
|
if (c->session == s) {
|
||||||
if (c->tty.sx < ssx)
|
if (c->tty.sx < ssx)
|
||||||
ssx = c->tty.sx;
|
ssx = c->tty.sx;
|
||||||
|
@ -109,6 +109,9 @@ static void tmate_header(struct tmate_unpacker *uk)
|
|||||||
if (gethostname(hostname, sizeof(hostname)) < 0)
|
if (gethostname(hostname, sizeof(hostname)) < 0)
|
||||||
tmate_fatal("cannot get hostname");
|
tmate_fatal("cannot get hostname");
|
||||||
|
|
||||||
|
tmate_notify("Remote session read only: ssh ro-%s@%s.%s (clear your screen if you share this)",
|
||||||
|
tmate_session_token_ro, hostname, TMATE_DOMAIN);
|
||||||
|
|
||||||
tmate_notify("Remote session: ssh %s@%s.%s",
|
tmate_notify("Remote session: ssh %s@%s.%s",
|
||||||
tmate_session_token, hostname, TMATE_DOMAIN);
|
tmate_session_token, hostname, TMATE_DOMAIN);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
struct tmate_encoder *tmate_encoder;
|
struct tmate_encoder *tmate_encoder;
|
||||||
int tmux_socket_fd;
|
int tmux_socket_fd;
|
||||||
const char *tmate_session_token = "main";
|
const char *tmate_session_token = "main";
|
||||||
|
const char *tmate_session_token_ro = "ro-main";
|
||||||
|
|
||||||
static char *log_path; /* NULL means stderr */
|
static char *log_path; /* NULL means stderr */
|
||||||
static char *cmdline;
|
static char *cmdline;
|
||||||
@ -97,19 +98,6 @@ int main(int argc, char **argv, char **envp)
|
|||||||
tmate_ssh_server_main(keys_dir, port);
|
tmate_ssh_server_main(keys_dir, port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static void set_session_token(struct tmate_ssh_client *client,
|
|
||||||
const char *token)
|
|
||||||
{
|
|
||||||
tmate_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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char tmate_token_digits[] = "abcdefghijklmnopqrstuvwxyz"
|
static char tmate_token_digits[] = "abcdefghijklmnopqrstuvwxyz"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
@ -126,11 +114,37 @@ static char *get_random_token(void)
|
|||||||
token[i] = tmate_token_digits[token[i] % NUM_DIGITS];
|
token[i] = tmate_token_digits[token[i] % NUM_DIGITS];
|
||||||
token[i] = 0;
|
token[i] = 0;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_session_token(struct tmate_ssh_client *client,
|
||||||
|
const char *token)
|
||||||
|
{
|
||||||
|
tmate_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);
|
||||||
|
}
|
||||||
|
static void create_session_ro_symlink(void)
|
||||||
|
{
|
||||||
|
char session_ro_path[MAXPATHLEN];
|
||||||
|
|
||||||
|
tmate_session_token_ro = get_random_token();
|
||||||
#ifdef DEVENV
|
#ifdef DEVENV
|
||||||
strcpy(token, "SUPERSECURETOKENFORDEVENV");
|
strcpy((char *)tmate_session_token_ro, "READONLYTOKENFORDEVENV000");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return token;
|
strcpy(session_ro_path, TMATE_WORKDIR "/sessions/");
|
||||||
|
strcat(session_ro_path, tmate_session_token_ro);
|
||||||
|
|
||||||
|
unlink(session_ro_path);
|
||||||
|
if (symlink(tmate_session_token, session_ro_path) < 0)
|
||||||
|
tmate_fatal("Cannot create read-only symlink");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int validate_token(const char *token)
|
static int validate_token(const char *token)
|
||||||
@ -254,6 +268,10 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
|||||||
struct tmate_decoder decoder;
|
struct tmate_decoder decoder;
|
||||||
|
|
||||||
token = get_random_token();
|
token = get_random_token();
|
||||||
|
#ifdef DEVENV
|
||||||
|
strcpy(token, "SUPERSECURETOKENFORDEVENV");
|
||||||
|
#endif
|
||||||
|
|
||||||
set_session_token(client, token);
|
set_session_token(client, token);
|
||||||
free(token);
|
free(token);
|
||||||
|
|
||||||
@ -263,6 +281,8 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
|||||||
if (tmux_socket_fd < 0)
|
if (tmux_socket_fd < 0)
|
||||||
tmate_fatal("Cannot create to the tmux socket");
|
tmate_fatal("Cannot create to the tmux socket");
|
||||||
|
|
||||||
|
create_session_ro_symlink();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Needed to initialize the database used in tty-term.c.
|
* Needed to initialize the database used in tty-term.c.
|
||||||
* We won't have access to it once in the jail.
|
* We won't have access to it once in the jail.
|
||||||
@ -286,11 +306,19 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
char *argv[] = {(char *)"attach", NULL};
|
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;
|
char *token = client->username;
|
||||||
|
struct stat fstat;
|
||||||
int slave_pty;
|
int slave_pty;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* the "ro-" part is just sugar, we don't care about it */
|
||||||
|
if (!memcmp("ro-", token, 3))
|
||||||
|
token += 3;
|
||||||
|
|
||||||
if (validate_token(token) < 0) {
|
if (validate_token(token) < 0) {
|
||||||
ssh_echo(client, BAD_TOKEN_ERROR_STR);
|
ssh_echo(client, BAD_TOKEN_ERROR_STR);
|
||||||
tmate_fatal("Bad token");
|
tmate_fatal("Bad token");
|
||||||
@ -307,6 +335,22 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
|||||||
tmate_fatal("Expired token");
|
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.
|
||||||
|
*/
|
||||||
|
client->readonly = 0;
|
||||||
|
if (lstat(socket_path, &fstat) < 0)
|
||||||
|
tmate_fatal("Cannot fstat()");
|
||||||
|
if (S_ISLNK(fstat.st_mode)) {
|
||||||
|
client->readonly = 1;
|
||||||
|
argv = argv_ro;
|
||||||
|
argc = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (openpty(&client->pty, &slave_pty, NULL, NULL, NULL) < 0)
|
if (openpty(&client->pty, &slave_pty, NULL, NULL, NULL) < 0)
|
||||||
tmate_fatal("Cannot allocate pty");
|
tmate_fatal("Cannot allocate pty");
|
||||||
|
|
||||||
@ -324,7 +368,7 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
tmate_ssh_client_pty_init(client);
|
tmate_ssh_client_pty_init(client);
|
||||||
|
|
||||||
ret = client_main(1, argv, IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
ret = client_main(argc, argv, IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
||||||
tmate_flush_pty(client);
|
tmate_flush_pty(client);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,9 @@ static void consume_channel(struct tmate_ssh_client *client)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (client->readonly)
|
||||||
|
continue;
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
setblocking(client->pty, 1);
|
setblocking(client->pty, 1);
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
|
2
tmate.h
2
tmate.h
@ -102,6 +102,7 @@ struct tmate_ssh_client {
|
|||||||
/* only for client-pty */
|
/* only for client-pty */
|
||||||
int pty;
|
int pty;
|
||||||
struct event ev_pty;
|
struct event ev_pty;
|
||||||
|
int readonly;
|
||||||
};
|
};
|
||||||
extern void tmate_ssh_client_init(struct tmate_ssh_client *client,
|
extern void tmate_ssh_client_init(struct tmate_ssh_client *client,
|
||||||
struct tmate_encoder *encoder,
|
struct tmate_encoder *encoder,
|
||||||
@ -136,6 +137,7 @@ extern void tmate_ssh_server_main(const char *keys_dir, int port);
|
|||||||
extern struct tmate_encoder *tmate_encoder;
|
extern struct tmate_encoder *tmate_encoder;
|
||||||
extern int tmux_socket_fd;
|
extern int tmux_socket_fd;
|
||||||
extern const char *tmate_session_token;
|
extern const char *tmate_session_token;
|
||||||
|
extern const char *tmate_session_token_ro;
|
||||||
|
|
||||||
extern void tmate_get_random_bytes(void *buffer, ssize_t len);
|
extern void tmate_get_random_bytes(void *buffer, ssize_t len);
|
||||||
extern long tmate_get_random_long(void);
|
extern long tmate_get_random_long(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user