1
0
mirror of https://github.com/tmate-io/tmate-ssh-server.git synced 2020-11-18 19:53:51 -08:00

Jail in place

Still missing the network isolation.
Maybe a iptable filtered by uid would work.
This commit is contained in:
Nicolas Viennot 2013-06-11 03:56:47 -04:00
parent 31b5c08472
commit 3ee065ce52
7 changed files with 106 additions and 12 deletions

View File

@ -84,12 +84,7 @@ server_create_socket(void)
fatal("socket failed");
}
#ifdef TMATE_SLAVE
if (access(sa.sun_path, F_OK) == 0)
tmate_fatal("session exists");
#else
unlink(sa.sun_path);
#endif
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket failed");

View File

@ -2,6 +2,16 @@
#include <stdlib.h>
#include <unistd.h>
#include <libssh/libssh.h>
#include <sys/stat.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#ifdef HAVE_CURSES_H
#include <curses.h>
#else
#include <ncurses.h>
#endif
#include <term.h>
#include "tmate.h"
struct tmate_encoder *tmate_encoder;
@ -41,6 +51,12 @@ int main(int argc, char **argv)
}
log_open(debug_level, log_path);
if ((mkdir(TMATE_WORKDIR, 0700) < 0 && errno != EEXIST) ||
(mkdir(TMATE_WORKDIR "/sessions", 0700) < 0 && errno != EEXIST) ||
(mkdir(TMATE_WORKDIR "/jail", 0700) < 0 && errno != EEXIST))
tmate_fatal("Cannot prepare session in " TMATE_WORKDIR);
tmate_ssh_server_main(port);
return 0;
}
@ -48,7 +64,7 @@ int main(int argc, char **argv)
static void set_session_token(const char *token)
{
tmate_session_token = xstrdup(token);
strcpy(socket_path, "/tmp/tmate-slave-");
strcpy(socket_path, TMATE_WORKDIR "/sessions/");
strcat(socket_path, token);
}
@ -62,6 +78,11 @@ static char *get_random_token(void)
int i;
char *token = xmalloc(TMATE_TOKEN_LEN + 1);
#if 0
strcpy(token, "TOKENTOKENTOKENTOKENTOKEN");
return token;
#endif
ssh_get_random(token, TMATE_TOKEN_LEN, 0);
for (i = 0; i < TMATE_TOKEN_LEN; i++)
token[i] = tmate_token_digits[token[i] % NUM_DIGITS];
@ -134,6 +155,50 @@ static void close_fds_except(int *fd_to_preserve, int num_fds)
}
}
static void jail(void)
{
struct passwd *pw;
uid_t uid;
gid_t gid;
pw = getpwnam(TMATE_JAIL_USER);
if (!pw) {
tmate_fatal("Cannot get the /etc/passwd entry for %s",
TMATE_JAIL_USER);
}
uid = pw->pw_uid;
gid = pw->pw_gid;
/*
* We are already in a new PID namespace (from the server fork).
*/
if (chroot(TMATE_WORKDIR "/jail") < 0)
tmate_fatal("Cannot chroot()");
if (chdir("/") < 0)
tmate_fatal("Cannot chdir()");
if (setgroups(1, (gid_t[]){gid}) < 0)
tmate_fatal("Cannot setgroups()");
if (setresuid(uid, uid, uid) < 0)
tmate_fatal("Cannot setresuid()");
if (setresuid(gid, gid, gid) < 0)
tmate_fatal("Cannot setresgid()");
tmate_debug("Dropped priviledges to %s (%d,%d)",
TMATE_JAIL_USER, uid, gid);
}
static void setup_ncurse(int fd, const char *name)
{
int error;
if (setupterm(name, fd, &error) != OK)
tmate_fatal("Cannot setup terminal");
}
static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
{
char *token;
@ -150,8 +215,14 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
if (tmux_socket_fd < 0)
tmate_fatal("Cannot create to the tmux socket");
/*
* 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");
close_fds_except((int[]){tmux_socket_fd, ssh_get_fd(client->session),
fileno(log_file)}, 7);
jail();
ev_base = osdep_event_init();
@ -195,9 +266,11 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
dup2(slave_pty, STDOUT_FILENO);
dup2(slave_pty, STDERR_FILENO);
setup_ncurse(slave_pty, "screen-256color");
close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
tmux_socket_fd, ssh_get_fd(client->session),
client->pty, fileno(log_file)}, 7);
jail();
ev_base = osdep_event_init();

View File

@ -3,6 +3,8 @@
#include <libssh/server.h>
#include <libssh/callbacks.h>
extern int server_shutdown;
static void consume_channel(struct tmate_ssh_client *client)
{
char *buf;
@ -18,7 +20,8 @@ static void consume_channel(struct tmate_ssh_client *client)
if (len < 0) {
tmate_debug("Error reading from channel: %s",
ssh_get_error(client->session));
exit(1);
server_shutdown = 1;
break;
}
if (len == 0)
break;
@ -35,7 +38,8 @@ static void on_session_event(struct tmate_ssh_client *client)
consume_channel(client);
if (!ssh_is_connected(session)) {
tmate_debug("Disconnected");
exit(1);
server_shutdown = 1;
return;
}
}
@ -68,7 +72,8 @@ static void flush_input_stream(struct tmate_ssh_client *client)
if (written < 0) {
tmate_debug("Error writing to channel: %s",
ssh_get_error(client->session));
exit(1);
server_shutdown = 1;
break;
}
evbuffer_drain(evb, written);

View File

@ -3,9 +3,11 @@
#include <libssh/callbacks.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <sched.h>
#include <stdio.h>
#include <event.h>
#include <sys/wait.h>
#include "tmate.h"
@ -160,6 +162,8 @@ static void handle_sigchld(void)
int status, child_dead, child_exit_status;
pid_t pid;
/* TODO cleanup the socket when the client dies */
while ((pid = waitpid(0, &status, WNOHANG)) > 0) {
child_dead = 0;
@ -208,6 +212,14 @@ static struct ssh_callbacks_struct ssh_session_callbacks = {
.log_function = ssh_log_cb
};
static pid_t namespace_fork(void)
{
/* XXX we are breaking getpid() libc cache. Bad libc. */
unsigned long flags;
flags = CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNS | CLONE_NEWNET;
return syscall(SYS_clone, flags | SIGCHLD, NULL, NULL, NULL);
}
void tmate_ssh_server_main(int port)
{
struct tmate_ssh_client _client;
@ -245,8 +257,8 @@ void tmate_ssh_server_main(int port)
if (ssh_bind_accept(bind, client->session) < 0)
tmate_fatal("Error accepting connection: %s", ssh_get_error(bind));
if ((pid = fork()) < 0)
tmate_fatal("Can't fork");
if ((pid = namespace_fork()) < 0)
tmate_fatal("Can't fork in new namespace");
if (pid) {
ssh_free(client->session);

View File

@ -101,6 +101,8 @@ extern void tmate_ssh_server_main(int port);
/* tmate-slave.c */
#define TMATE_TOKEN_LEN 25
#define TMATE_WORKDIR "/tmp/tmate"
#define TMATE_JAIL_USER "nobody"
extern struct tmate_encoder *tmate_encoder;
extern int tmux_socket_fd;

View File

@ -333,6 +333,8 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
memset(term->codes, 0, sizeof term->codes);
LIST_INSERT_HEAD(&tty_terms, term, entry);
/* we are in a jail, no access to files */
#ifndef TMATE_SLAVE
/* Set up curses terminal. */
if (setupterm(name, fd, &error) != OK) {
switch (error) {
@ -353,6 +355,7 @@ tty_term_find(char *name, int fd, const char *overrides, char **cause)
}
goto error;
}
#endif
/* Fill in codes. */
for (i = 0; i < NTTYCODE; i++) {

4
tty.c
View File

@ -72,9 +72,13 @@ tty_init(struct tty *tty, struct client *c, int fd, char *term)
tty->fd = fd;
tty->client = c;
#ifdef TMATE_SLAVE
tty->path = NULL;
#else
if ((path = ttyname(fd)) == NULL)
fatalx("ttyname failed");
tty->path = xstrdup(path);
#endif
tty->cstyle = 0;
tty->ccolour = xstrdup("");