mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Cleanup.
- Log only to syslog or stderr - Removed the record/replay - added ECDSA keys
This commit is contained in:
parent
c7c436eff1
commit
31cc091823
@ -181,7 +181,6 @@ dist_tmate_slave_SOURCES = \
|
|||||||
tmate-debug.c \
|
tmate-debug.c \
|
||||||
tmate-decoder.c \
|
tmate-decoder.c \
|
||||||
tmate-encoder.c \
|
tmate-encoder.c \
|
||||||
tmate-replayer.c \
|
|
||||||
tmate-slave.c \
|
tmate-slave.c \
|
||||||
tmate-ssh-client-pty.c \
|
tmate-ssh-client-pty.c \
|
||||||
tmate-ssh-client.c \
|
tmate-ssh-client.c \
|
||||||
|
@ -4,10 +4,10 @@ gen_key() {
|
|||||||
ks="${keytype}_"
|
ks="${keytype}_"
|
||||||
key="keys/ssh_host_${ks}key"
|
key="keys/ssh_host_${ks}key"
|
||||||
if [ ! -e "${key}" ] ; then
|
if [ ! -e "${key}" ] ; then
|
||||||
ssh-keygen -t ${keytype} -f "${key}" -N ''
|
ssh-keygen -t ${keytype} -f "${key}" -N '' -E md5
|
||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
mkdir -p keys
|
mkdir -p keys
|
||||||
gen_key dsa && gen_key rsa && gen_key ecdsa || exit 1
|
gen_key rsa && gen_key ecdsa || exit 1
|
||||||
|
130
log.c
130
log.c
@ -29,89 +29,68 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
|
||||||
/* Log file, if needed. */
|
|
||||||
FILE *log_file;
|
FILE *log_file;
|
||||||
|
|
||||||
/* Debug level. */
|
struct logging_settings {
|
||||||
int log_level = 0;
|
const char *program_name;
|
||||||
|
bool use_syslog;
|
||||||
|
int log_level;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct logging_settings log_settings;
|
||||||
|
|
||||||
void log_event_cb(int, const char *);
|
void log_event_cb(int, const char *);
|
||||||
void log_vwrite(const char *, va_list);
|
void log_vwrite(int, const char *, va_list);
|
||||||
__dead void log_vfatal(const char *, va_list);
|
__dead void log_vfatal(const char *, va_list);
|
||||||
|
|
||||||
/* Log callback for libevent. */
|
|
||||||
void
|
void
|
||||||
log_event_cb(unused int severity, const char *msg)
|
log_event_cb(unused int severity, const char *msg)
|
||||||
{
|
{
|
||||||
log_warnx("%s", msg);
|
log_warnx("%s", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open logging to file. */
|
void init_logging(const char *program_name, bool use_syslog, int log_level)
|
||||||
void
|
|
||||||
log_open(int level, const char *path)
|
|
||||||
{
|
{
|
||||||
FILE *f;
|
log_settings.log_level = log_level;
|
||||||
|
log_settings.use_syslog = use_syslog;
|
||||||
|
log_settings.program_name = xstrdup(program_name);
|
||||||
|
|
||||||
if (path) {
|
if (use_syslog) {
|
||||||
f = fopen(path, "a");
|
openlog(program_name, LOG_CONS | LOG_PID, LOG_USER);
|
||||||
if (!f) {
|
setlogmask(LOG_UPTO(log_level));
|
||||||
if (log_file) {
|
} else {
|
||||||
log_info("cannot reopen log file");
|
log_file = fdopen(dup(STDERR_FILENO), "a");
|
||||||
return;
|
if (!log_file)
|
||||||
}
|
|
||||||
fprintf(stderr, "cannot open log file %s\n", path);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
f = fdopen(dup(STDERR_FILENO), "a");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log_file)
|
|
||||||
fclose(log_file);
|
|
||||||
|
|
||||||
log_file = f;
|
|
||||||
log_level = level;
|
|
||||||
|
|
||||||
setlinebuf(log_file);
|
|
||||||
event_set_log_callback(log_event_cb);
|
event_set_log_callback(log_event_cb);
|
||||||
|
|
||||||
tzset();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close logging. */
|
|
||||||
void
|
|
||||||
log_close(void)
|
|
||||||
{
|
|
||||||
if (log_file != NULL)
|
|
||||||
fclose(log_file);
|
|
||||||
|
|
||||||
event_set_log_callback(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a log message. */
|
/* Write a log message. */
|
||||||
void
|
void
|
||||||
log_vwrite(const char *msg, va_list ap)
|
log_vwrite(int level, const char *msg, va_list ap)
|
||||||
{
|
{
|
||||||
char time_str[100];
|
char *fmt = NULL;
|
||||||
time_t now;
|
|
||||||
struct tm *tm;
|
|
||||||
|
|
||||||
char *fmt;
|
if (log_settings.log_level < level)
|
||||||
|
|
||||||
if (log_file == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* XXX Should we do UTC instead of local time? */
|
if (tmate_session_token) {
|
||||||
now = time(NULL);
|
if (asprintf(&fmt, "[%s] %s", tmate_session_token, msg) < 0)
|
||||||
tm = localtime(&now);
|
|
||||||
|
|
||||||
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm);
|
|
||||||
|
|
||||||
if (asprintf(&fmt, "%s [%s] %s\n", time_str, tmate_session_token, msg) == -1)
|
|
||||||
exit(1);
|
|
||||||
if (vfprintf(log_file, fmt, ap) == -1)
|
|
||||||
exit(1);
|
exit(1);
|
||||||
|
msg = fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_settings.use_syslog) {
|
||||||
|
vsyslog(level, msg, ap);
|
||||||
|
} else {
|
||||||
|
fprintf(log_file, "<%d> ", level);
|
||||||
|
vfprintf(log_file, msg, ap);
|
||||||
|
fprintf(log_file, "\n");
|
||||||
fflush(log_file);
|
fflush(log_file);
|
||||||
|
}
|
||||||
|
|
||||||
free(fmt);
|
free(fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +104,7 @@ log_warn(const char *msg, ...)
|
|||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
|
if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
|
||||||
exit(1);
|
exit(1);
|
||||||
log_vwrite(fmt, ap);
|
log_vwrite(LOG_WARNING, fmt, ap);
|
||||||
free(fmt);
|
free(fmt);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
@ -137,7 +116,7 @@ log_warnx(const char *msg, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
log_vwrite(msg, ap);
|
log_vwrite(LOG_WARNING, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,12 +126,10 @@ log_info(const char *msg, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (log_level > -1) {
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
log_vwrite(msg, ap);
|
log_vwrite(LOG_NOTICE, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Log a debug message. */
|
/* Log a debug message. */
|
||||||
void printflike1
|
void printflike1
|
||||||
@ -160,12 +137,10 @@ log_debug(const char *msg, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (log_level > 0) {
|
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
log_vwrite(msg, ap);
|
log_vwrite(LOG_INFO, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Log a debug message at level 2. */
|
/* Log a debug message at level 2. */
|
||||||
void printflike1
|
void printflike1
|
||||||
@ -173,11 +148,12 @@ log_debug2(const char *msg, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
if (log_level > 1) {
|
/* Not going with crazy logging on tmux */
|
||||||
|
#ifndef TMATE_SLAVE
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
log_vwrite(msg, ap);
|
log_vwrite(LOG_DEBUG, msg, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log a critical error, with error string if necessary, and die. */
|
/* Log a critical error, with error string if necessary, and die. */
|
||||||
@ -189,11 +165,11 @@ log_vfatal(const char *msg, va_list ap)
|
|||||||
if (errno != 0) {
|
if (errno != 0) {
|
||||||
if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
|
if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
|
||||||
exit(1);
|
exit(1);
|
||||||
log_vwrite(fmt, ap);
|
log_vwrite(LOG_CRIT, fmt, ap);
|
||||||
} else {
|
} else {
|
||||||
if (asprintf(&fmt, "fatal: %s", msg) == -1)
|
if (asprintf(&fmt, "fatal: %s", msg) == -1)
|
||||||
exit(1);
|
exit(1);
|
||||||
log_vwrite(fmt, ap);
|
log_vwrite(LOG_CRIT, fmt, ap);
|
||||||
}
|
}
|
||||||
free(fmt);
|
free(fmt);
|
||||||
|
|
||||||
@ -220,3 +196,21 @@ log_fatalx(const char *msg, ...)
|
|||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
log_vfatal(msg, ap);
|
log_vfatal(msg, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printflike2 tmate_log(int level, const char *msg, ...)
|
||||||
|
{
|
||||||
|
char *fmt;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
if (log_settings.log_level < level)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(ap, msg);
|
||||||
|
|
||||||
|
if (asprintf(&fmt, "(tmate) %s", msg) < 0)
|
||||||
|
exit(1);
|
||||||
|
log_vwrite(level, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
free(fmt);
|
||||||
|
}
|
||||||
|
@ -119,14 +119,14 @@ static void tmate_header(struct tmate_decoder *decoder,
|
|||||||
|
|
||||||
free(client_version);
|
free(client_version);
|
||||||
|
|
||||||
if (tmate_port != 22)
|
if (tmate_settings.ssh_port != 22)
|
||||||
sprintf(port_arg, " -p%d", tmate_port);
|
sprintf(port_arg, " -p%d", tmate_settings.ssh_port);
|
||||||
|
|
||||||
sprintf(tmp, "ssh%s ro-%s@%s", port_arg, tmate_session_token_ro, tmate_host);
|
sprintf(tmp, "ssh%s ro-%s@%s", port_arg, tmate_session_token_ro, tmate_settings.tmate_host);
|
||||||
tmate_notify("Remote session read only: %s (clear your screen if you share this)", tmp);
|
tmate_notify("Remote session read only: %s (clear your screen if you share this)", tmp);
|
||||||
tmate_send_env("tmate_ssh_ro", tmp);
|
tmate_send_env("tmate_ssh_ro", tmp);
|
||||||
|
|
||||||
sprintf(tmp, "ssh%s %s@%s", port_arg, tmate_session_token, tmate_host);
|
sprintf(tmp, "ssh%s %s@%s", port_arg, tmate_session_token, tmate_settings.tmate_host);
|
||||||
tmate_notify("Remote session: %s", tmp);
|
tmate_notify("Remote session: %s", tmp);
|
||||||
tmate_send_env("tmate_ssh", tmp);
|
tmate_send_env("tmate_ssh", tmp);
|
||||||
|
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
#include <ctype.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "tmate.h"
|
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
|
|
||||||
#define READ_MAX_SIZE 1024
|
|
||||||
#define TIMER_INERVAL_USEC 1000
|
|
||||||
|
|
||||||
extern int server_shutdown;
|
|
||||||
extern void server_send_shutdown(void);
|
|
||||||
|
|
||||||
static void start_timer(struct tmate_replayer *replayer);
|
|
||||||
|
|
||||||
static void on_read_timer(evutil_socket_t fd, short what, void *arg)
|
|
||||||
{
|
|
||||||
struct tmate_replayer *replayer = arg;
|
|
||||||
char *buf;
|
|
||||||
ssize_t len;
|
|
||||||
|
|
||||||
if (replayer->log_fd < 0) {
|
|
||||||
evtimer_del(&replayer->ev_read_timer);
|
|
||||||
server_shutdown = 1;
|
|
||||||
server_send_shutdown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmate_decoder_get_buffer(replayer->decoder, &buf, &len);
|
|
||||||
if (len == 0)
|
|
||||||
tmate_fatal("Decoder buffer full");
|
|
||||||
|
|
||||||
if (len > READ_MAX_SIZE)
|
|
||||||
len = READ_MAX_SIZE;
|
|
||||||
|
|
||||||
len = read(replayer->log_fd, buf, len);
|
|
||||||
if (len < 0)
|
|
||||||
tmate_fatal("cannot read from replay log file");
|
|
||||||
|
|
||||||
if (len == 0) {
|
|
||||||
tmate_info("Replay file reached EOF");
|
|
||||||
replayer->log_fd = -1;
|
|
||||||
} else {
|
|
||||||
tmate_decoder_commit(replayer->decoder, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
start_timer(replayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void start_timer(struct tmate_replayer *replayer)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = TIMER_INERVAL_USEC;
|
|
||||||
|
|
||||||
evtimer_assign(&replayer->ev_read_timer, ev_base,
|
|
||||||
on_read_timer, replayer);
|
|
||||||
evtimer_add(&replayer->ev_read_timer, &tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tmate_replayer_init(struct tmate_replayer *replayer,
|
|
||||||
struct tmate_decoder *decoder,
|
|
||||||
int log_fd)
|
|
||||||
{
|
|
||||||
replayer->decoder = decoder;
|
|
||||||
replayer->log_fd = log_fd;
|
|
||||||
|
|
||||||
start_timer(replayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
121
tmate-slave.c
121
tmate-slave.c
@ -15,39 +15,37 @@
|
|||||||
#include <term.h>
|
#include <term.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/syslog.h>
|
||||||
#include "tmate.h"
|
#include "tmate.h"
|
||||||
|
|
||||||
int tmate_port = TMATE_DEFAULT_PORT;
|
|
||||||
char *tmate_host;
|
|
||||||
|
|
||||||
struct tmate_decoder *tmate_decoder;
|
struct tmate_decoder *tmate_decoder;
|
||||||
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;
|
||||||
const char *tmate_session_token_ro = "ro-main";
|
const char *tmate_session_token_ro;
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
extern FILE *log_file;
|
||||||
int tmate_session_log_fd;
|
|
||||||
static void tmate_replay_slave_server(const char *replay_file);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char *log_path; /* NULL means stderr */
|
|
||||||
static char *cmdline;
|
static char *cmdline;
|
||||||
static char *cmdline_end;
|
static char *cmdline_end;
|
||||||
static int dev_urandom_fd;
|
static int dev_urandom_fd;
|
||||||
|
|
||||||
extern FILE *log_file;
|
|
||||||
extern int server_create_socket(void);
|
extern int server_create_socket(void);
|
||||||
extern int client_connect(char *path, int start_server);
|
extern int client_connect(char *path, int start_server);
|
||||||
|
|
||||||
|
struct tmate_settings tmate_settings = {
|
||||||
|
.keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR,
|
||||||
|
.ssh_port = TMATE_SSH_DEFAULT_PORT,
|
||||||
|
.master_hostname = TMATE_DEFAULT_MASTER_HOST,
|
||||||
|
.master_port = TMATE_DEFAULT_MASTER_PORT,
|
||||||
|
.tmate_host = NULL,
|
||||||
|
.log_level = LOG_NOTICE,
|
||||||
|
.use_syslog = false,
|
||||||
|
};
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "usage: tmate-slave [-k keys_dir] [-l logfile] [-p port] [-r logfile] [-h host] [-v]\n");
|
fprintf(stderr, "usage: tmate-slave [-k keys_dir] [-p port] [-m master_hostname] [-q master_port] [-s] [-v]\n");
|
||||||
}
|
|
||||||
|
|
||||||
void tmate_reopen_logfile(void)
|
|
||||||
{
|
|
||||||
log_open(debug_level, log_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tmate_get_random_bytes(void *buffer, ssize_t len)
|
void tmate_get_random_bytes(void *buffer, ssize_t len)
|
||||||
@ -66,34 +64,29 @@ long tmate_get_random_long(void)
|
|||||||
int main(int argc, char **argv, char **envp)
|
int main(int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
const char *keys_dir = "keys";
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
const char *replay_file = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "p:l:vk:r:h:")) != -1) {
|
while ((opt = getopt(argc, argv, "k:p:lvm:q:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'p':
|
case 'p':
|
||||||
tmate_port = atoi(optarg);
|
tmate_settings.ssh_port = atoi(optarg);
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
log_path = optarg;
|
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
keys_dir = optarg;
|
tmate_settings.keys_dir = xstrdup(optarg);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
tmate_settings.use_syslog = true;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
debug_level++;
|
tmate_settings.log_level++;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'm':
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
tmate_settings.master_hostname = xstrdup(optarg);
|
||||||
replay_file = optarg;
|
break;
|
||||||
#else
|
case 'q':
|
||||||
fprintf(stderr, "Record/Replay not enabled\n");
|
tmate_settings.master_port = atoi(optarg);
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
tmate_host = xstrdup(optarg);
|
tmate_settings.tmate_host = xstrdup(optarg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
@ -101,36 +94,30 @@ int main(int argc, char **argv, char **envp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tmate_host) {
|
if (!tmate_settings.tmate_host) {
|
||||||
char hostname[255];
|
char hostname[255];
|
||||||
if (gethostname(hostname, sizeof(hostname)) < 0)
|
if (gethostname(hostname, sizeof(hostname)) < 0)
|
||||||
tmate_fatal("cannot get hostname");
|
tmate_fatal("cannot get hostname");
|
||||||
tmate_host = xstrdup(hostname);
|
tmate_settings.tmate_host = xstrdup(hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdline = *argv;
|
cmdline = *argv;
|
||||||
cmdline_end = *envp;
|
cmdline_end = *envp;
|
||||||
|
|
||||||
tmate_reopen_logfile();
|
init_logging("tmate-ssh",
|
||||||
|
tmate_settings.use_syslog, tmate_settings.log_level);
|
||||||
|
|
||||||
tmate_preload_trace_lib();
|
tmate_preload_trace_lib();
|
||||||
|
|
||||||
if ((dev_urandom_fd = open("/dev/urandom", O_RDONLY)) < 0)
|
if ((dev_urandom_fd = open("/dev/urandom", O_RDONLY)) < 0)
|
||||||
tmate_fatal("Cannot open /dev/urandom");
|
tmate_fatal("Cannot open /dev/urandom");
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
if (replay_file) {
|
|
||||||
tmate_replay_slave_server(replay_file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((mkdir(TMATE_WORKDIR, 0700) < 0 && errno != EEXIST) ||
|
if ((mkdir(TMATE_WORKDIR, 0700) < 0 && errno != EEXIST) ||
|
||||||
(mkdir(TMATE_WORKDIR "/sessions", 0700) < 0 && errno != EEXIST) ||
|
(mkdir(TMATE_WORKDIR "/sessions", 0700) < 0 && errno != EEXIST) ||
|
||||||
(mkdir(TMATE_WORKDIR "/jail", 0700) < 0 && errno != EEXIST))
|
(mkdir(TMATE_WORKDIR "/jail", 0700) < 0 && errno != EEXIST))
|
||||||
tmate_fatal("Cannot prepare session in " TMATE_WORKDIR);
|
tmate_fatal("Cannot prepare session in " TMATE_WORKDIR);
|
||||||
|
|
||||||
tmate_ssh_server_main(keys_dir, tmate_port);
|
tmate_ssh_server_main(tmate_settings.keys_dir, tmate_settings.ssh_port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,32 +283,6 @@ static void setup_ncurse(int fd, const char *name)
|
|||||||
tmate_fatal("Cannot setup terminal");
|
tmate_fatal("Cannot setup terminal");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
static void tmate_replay_slave_server(const char *replay_file)
|
|
||||||
{
|
|
||||||
struct tmate_decoder decoder;
|
|
||||||
struct tmate_replayer replayer;
|
|
||||||
|
|
||||||
tmate_debug("Replaying slave server with %s", replay_file);
|
|
||||||
|
|
||||||
tmux_socket_fd = server_create_socket();
|
|
||||||
if (tmux_socket_fd < 0)
|
|
||||||
tmate_fatal("Cannot create to the tmux socket");
|
|
||||||
|
|
||||||
tmate_session_log_fd = open(replay_file, O_RDONLY);
|
|
||||||
if (tmate_session_log_fd < 0)
|
|
||||||
tmate_fatal("cannot open session-dump.log");
|
|
||||||
|
|
||||||
ev_base = osdep_event_init();
|
|
||||||
|
|
||||||
tmate_decoder_init(&decoder);
|
|
||||||
tmate_replayer_init(&replayer, &decoder, tmate_session_log_fd);
|
|
||||||
|
|
||||||
tmux_server_init(IDENTIFY_UTF8 | IDENTIFY_256COLOURS);
|
|
||||||
/* never reached */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
char *token;
|
char *token;
|
||||||
@ -339,7 +300,6 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
|||||||
tmate_debug("Spawning slave server for %s at %s (%s)",
|
tmate_debug("Spawning slave server for %s at %s (%s)",
|
||||||
client->username, client->ip_address, client->pubkey);
|
client->username, client->ip_address, client->pubkey);
|
||||||
|
|
||||||
|
|
||||||
tmux_socket_fd = server_create_socket();
|
tmux_socket_fd = server_create_socket();
|
||||||
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");
|
||||||
@ -354,14 +314,7 @@ static void tmate_spawn_slave_server(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
close_fds_except((int[]){tmux_socket_fd,
|
close_fds_except((int[]){tmux_socket_fd,
|
||||||
ssh_get_fd(client->session),
|
ssh_get_fd(client->session),
|
||||||
fileno(log_file)}, 3);
|
log_file ? fileno(log_file) : -1}, 3);
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
tmate_session_log_fd = open("session-log.log",
|
|
||||||
O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
|
||||||
if (tmate_session_log_fd < 0)
|
|
||||||
tmate_fatal("cannot open session-dump.log");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
jail();
|
jail();
|
||||||
|
|
||||||
@ -395,7 +348,7 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
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("Invalid token");
|
||||||
}
|
}
|
||||||
|
|
||||||
set_session_token(client, token);
|
set_session_token(client, token);
|
||||||
@ -405,7 +358,7 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
tmux_socket_fd = client_connect(socket_path, 0);
|
tmux_socket_fd = client_connect(socket_path, 0);
|
||||||
if (tmux_socket_fd < 0) {
|
if (tmux_socket_fd < 0) {
|
||||||
random_sleep(); /* for timing attacks */
|
random_sleep(); /* for making timing attacks harder */
|
||||||
ssh_echo(client, EXPIRED_TOKEN_ERROR_STR);
|
ssh_echo(client, EXPIRED_TOKEN_ERROR_STR);
|
||||||
tmate_fatal("Expired token");
|
tmate_fatal("Expired token");
|
||||||
}
|
}
|
||||||
@ -436,7 +389,7 @@ static void tmate_spawn_slave_client(struct tmate_ssh_client *client)
|
|||||||
setup_ncurse(slave_pty, "screen-256color");
|
setup_ncurse(slave_pty, "screen-256color");
|
||||||
close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
|
close_fds_except((int[]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO,
|
||||||
tmux_socket_fd, ssh_get_fd(client->session),
|
tmux_socket_fd, ssh_get_fd(client->session),
|
||||||
client->pty, fileno(log_file)}, 7);
|
client->pty, log_file ? fileno(log_file) : -1}, 7);
|
||||||
jail();
|
jail();
|
||||||
|
|
||||||
ev_base = osdep_event_init();
|
ev_base = osdep_event_init();
|
||||||
|
@ -12,25 +12,6 @@ extern void server_send_shutdown(void);
|
|||||||
server_send_shutdown(); \
|
server_send_shutdown(); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
static void record_session_data(const char *buf, size_t len)
|
|
||||||
{
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
while (len > 0) {
|
|
||||||
ret = write(tmate_session_log_fd, buf, len);
|
|
||||||
if (ret < 0)
|
|
||||||
tmate_fatal("cannot save recording of the session");
|
|
||||||
|
|
||||||
buf += ret;
|
|
||||||
len -= ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline void record_session_data(const char *buf, size_t len)
|
|
||||||
{}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void consume_channel(struct tmate_ssh_client *client)
|
static void consume_channel(struct tmate_ssh_client *client)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -56,8 +37,6 @@ static void consume_channel(struct tmate_ssh_client *client)
|
|||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
record_session_data(buf, len);
|
|
||||||
|
|
||||||
tmate_decoder_commit(client->decoder, len);
|
tmate_decoder_commit(client->decoder, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,8 @@ static void client_bootstrap(struct tmate_ssh_client *client)
|
|||||||
ssh_session session = client->session;
|
ssh_session session = client->session;
|
||||||
ssh_message msg;
|
ssh_message msg;
|
||||||
|
|
||||||
|
tmate_notice("Bootstrapping ssh client ip=%s", client->ip_address);
|
||||||
|
|
||||||
/* new process group, we don't want to die with our parent (upstart) */
|
/* new process group, we don't want to die with our parent (upstart) */
|
||||||
setpgid(0, 0);
|
setpgid(0, 0);
|
||||||
|
|
||||||
@ -149,7 +151,8 @@ static void client_bootstrap(struct tmate_ssh_client *client)
|
|||||||
|
|
||||||
tmate_debug("Exchanging DH keys");
|
tmate_debug("Exchanging DH keys");
|
||||||
if (ssh_handle_key_exchange(session) < 0)
|
if (ssh_handle_key_exchange(session) < 0)
|
||||||
tmate_fatal("Error doing the key exchange");
|
tmate_fatal("Error doing the key exchange: %s",
|
||||||
|
ssh_get_error(session));
|
||||||
|
|
||||||
mainloop = ssh_event_new();
|
mainloop = ssh_event_new();
|
||||||
ssh_event_add_session(mainloop, session);
|
ssh_event_add_session(mainloop, session);
|
||||||
@ -189,18 +192,12 @@ static void handle_sigsegv(void)
|
|||||||
tmate_fatal("CRASHED");
|
tmate_fatal("CRASHED");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_sigusr1(void)
|
|
||||||
{
|
|
||||||
tmate_reopen_logfile();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void signal_handler(int sig)
|
static void signal_handler(int sig)
|
||||||
{
|
{
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGCHLD: handle_sigchld(); break;
|
case SIGCHLD: handle_sigchld(); break;
|
||||||
case SIGALRM: handle_sigalrm(); break;
|
case SIGALRM: handle_sigalrm(); break;
|
||||||
case SIGSEGV: handle_sigsegv(); break;
|
case SIGSEGV: handle_sigsegv(); break;
|
||||||
case SIGUSR1: handle_sigusr1(); break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +206,6 @@ static void setup_signals(void)
|
|||||||
signal(SIGCHLD, signal_handler);
|
signal(SIGCHLD, signal_handler);
|
||||||
signal(SIGALRM, signal_handler);
|
signal(SIGALRM, signal_handler);
|
||||||
signal(SIGSEGV, signal_handler);
|
signal(SIGSEGV, signal_handler);
|
||||||
signal(SIGUSR1, signal_handler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static pid_t namespace_fork(void)
|
static pid_t namespace_fork(void)
|
||||||
@ -260,7 +256,6 @@ static ssh_bind prepare_ssh(const char *keys_dir, int port)
|
|||||||
ssh_bind bind;
|
ssh_bind bind;
|
||||||
char buffer[PATH_MAX];
|
char buffer[PATH_MAX];
|
||||||
int verbosity = SSH_LOG_NOLOG;
|
int verbosity = SSH_LOG_NOLOG;
|
||||||
//int verbosity = SSH_LOG_PACKET;
|
|
||||||
|
|
||||||
ssh_set_log_callback(ssh_log_function);
|
ssh_set_log_callback(ssh_log_function);
|
||||||
|
|
||||||
@ -272,16 +267,16 @@ static ssh_bind prepare_ssh(const char *keys_dir, int port)
|
|||||||
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BANNER, TMATE_SSH_BANNER);
|
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BANNER, TMATE_SSH_BANNER);
|
||||||
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &verbosity);
|
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||||
|
|
||||||
sprintf(buffer, "%s/ssh_host_dsa_key", keys_dir);
|
|
||||||
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY, buffer);
|
|
||||||
|
|
||||||
sprintf(buffer, "%s/ssh_host_rsa_key", keys_dir);
|
sprintf(buffer, "%s/ssh_host_rsa_key", keys_dir);
|
||||||
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY, buffer);
|
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY, buffer);
|
||||||
|
|
||||||
|
sprintf(buffer, "%s/ssh_host_ecdsa_key", keys_dir);
|
||||||
|
ssh_bind_options_set(bind, SSH_BIND_OPTIONS_ECDSAKEY, buffer);
|
||||||
|
|
||||||
if (ssh_bind_listen(bind) < 0)
|
if (ssh_bind_listen(bind) < 0)
|
||||||
tmate_fatal("Error listening to socket: %s\n", ssh_get_error(bind));
|
tmate_fatal("Error listening to socket: %s\n", ssh_get_error(bind));
|
||||||
|
|
||||||
tmate_info("Accepting connections on %d", port);
|
tmate_notice("Accepting connections on %d", port);
|
||||||
|
|
||||||
return bind;
|
return bind;
|
||||||
}
|
}
|
||||||
@ -321,7 +316,7 @@ void tmate_ssh_server_main(const char *keys_dir, int port)
|
|||||||
ssh_free(client->session);
|
ssh_free(client->session);
|
||||||
} else {
|
} else {
|
||||||
ssh_bind_free(bind);
|
ssh_bind_free(bind);
|
||||||
tmate_session_token = ".........................";
|
tmate_session_token = "init";
|
||||||
client_bootstrap(client);
|
client_bootstrap(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
54
tmate.h
54
tmate.h
@ -1,6 +1,7 @@
|
|||||||
#ifndef TMATE_H
|
#ifndef TMATE_H
|
||||||
#define TMATE_H
|
#define TMATE_H
|
||||||
|
|
||||||
|
#include <sys/syslog.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
@ -8,15 +9,18 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
// #define TMATE_RECORD_REPLAY /* useful to debug crashes */
|
extern void init_logging(const char *program_name, bool use_syslog, int log_level);
|
||||||
|
extern void printflike2 tmate_log(int level, const char *msg, ...);
|
||||||
|
|
||||||
#define tmate_debug(str, ...) log_debug("[tmate] " str, ##__VA_ARGS__)
|
#define tmate_debug(str, ...) tmate_log(LOG_DEBUG, str, ##__VA_ARGS__)
|
||||||
#define tmate_info(str, ...) log_info("[tmate] " str, ##__VA_ARGS__)
|
#define tmate_info(str, ...) tmate_log(LOG_INFO, str, ##__VA_ARGS__)
|
||||||
|
#define tmate_notice(str, ...) tmate_log(LOG_NOTICE, str, ##__VA_ARGS__)
|
||||||
|
#define tmate_warn(str, ...) tmate_log(LOG_WARNING, str, ##__VA_ARGS__)
|
||||||
#define tmate_fatal(str, ...) \
|
#define tmate_fatal(str, ...) \
|
||||||
do { \
|
({ \
|
||||||
log_info("[tmate] FATAL " str, ##__VA_ARGS__); \
|
tmate_log(LOG_CRIT, "fatal: " str, ##__VA_ARGS__); \
|
||||||
exit(-1); \
|
exit(1); \
|
||||||
} while (0)
|
})
|
||||||
|
|
||||||
/* tmate-encoder.c */
|
/* tmate-encoder.c */
|
||||||
|
|
||||||
@ -84,22 +88,6 @@ extern void tmate_decoder_get_buffer(struct tmate_decoder *decoder,
|
|||||||
char **buf, size_t *len);
|
char **buf, size_t *len);
|
||||||
extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
|
extern void tmate_decoder_commit(struct tmate_decoder *decoder, size_t len);
|
||||||
|
|
||||||
#ifdef TMATE_RECORD_REPLAY
|
|
||||||
/* tmate-replayer.c */
|
|
||||||
|
|
||||||
struct tmate_replayer {
|
|
||||||
struct tmate_decoder *decoder;
|
|
||||||
int log_fd;
|
|
||||||
|
|
||||||
struct event ev_read_timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void tmate_replayer_init(struct tmate_replayer *replayer,
|
|
||||||
struct tmate_decoder *decoder,
|
|
||||||
int log_fd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* tmate-ssh-client.c */
|
/* tmate-ssh-client.c */
|
||||||
|
|
||||||
#define TMATE_ROLE_SERVER 1
|
#define TMATE_ROLE_SERVER 1
|
||||||
@ -153,12 +141,28 @@ extern void tmate_ssh_server_main(const char *keys_dir, int port);
|
|||||||
|
|
||||||
/* tmate-slave.c */
|
/* tmate-slave.c */
|
||||||
|
|
||||||
|
struct tmate_settings {
|
||||||
|
const char *keys_dir;
|
||||||
|
int ssh_port;
|
||||||
|
const char *master_hostname;
|
||||||
|
int master_port;
|
||||||
|
const char *tmate_host;
|
||||||
|
int log_level;
|
||||||
|
bool use_syslog;
|
||||||
|
};
|
||||||
|
extern struct tmate_settings tmate_settings;
|
||||||
|
|
||||||
#ifdef DEVENV
|
#ifdef DEVENV
|
||||||
#define TMATE_DEFAULT_PORT 2200
|
#define TMATE_SSH_DEFAULT_PORT 2200
|
||||||
#else
|
#else
|
||||||
#define TMATE_DEFAULT_PORT 22
|
#define TMATE_SSH_DEFAULT_PORT 22
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TMATE_SSH_DEFAULT_KEYS_DIR "keys"
|
||||||
|
|
||||||
|
#define TMATE_DEFAULT_MASTER_HOST NULL
|
||||||
|
#define TMATE_DEFAULT_MASTER_PORT 7000
|
||||||
|
|
||||||
#define TMATE_TOKEN_LEN 25
|
#define TMATE_TOKEN_LEN 25
|
||||||
#define TMATE_WORKDIR "/tmp/tmate"
|
#define TMATE_WORKDIR "/tmp/tmate"
|
||||||
#define TMATE_JAIL_USER "nobody"
|
#define TMATE_JAIL_USER "nobody"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user