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:
parent
31b5c08472
commit
3ee065ce52
5
server.c
5
server.c
@ -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");
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
2
tmate.h
2
tmate.h
@ -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;
|
||||
|
@ -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
4
tty.c
@ -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("");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user