mirror of
https://github.com/tmate-io/tmate-ssh-server.git
synced 2020-11-18 19:53:51 -08:00
Allow tmate daemon to specify a list of authorized SSH keys
This commit is contained in:
parent
48884c95c9
commit
e71bd675b5
@ -175,6 +175,7 @@ dist_tmate_ssh_server_SOURCES = \
|
||||
signal.c \
|
||||
status.c \
|
||||
style.c \
|
||||
tmate-auth-keys.c \
|
||||
tmate-daemon-decoder.c \
|
||||
tmate-daemon-encoder.c \
|
||||
tmate-daemon-legacy.c \
|
||||
|
20
client.c
20
client.c
@ -401,21 +401,25 @@ client_send_identify(const char *ttynam, const char *cwd)
|
||||
int fd, flags = client_flags;
|
||||
pid_t pid;
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
proc_send(client_peer, MSG_IDENTIFY_TMATE_IP_ADDRESS, -1,
|
||||
tmate_session->ssh_client.ip_address,
|
||||
strlen(tmate_session->ssh_client.ip_address) + 1);
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_TMATE_PUBKEY, -1,
|
||||
if (tmate_session->ssh_client.pubkey) {
|
||||
proc_send(client_peer, MSG_IDENTIFY_TMATE_AUTH_PUBKEY, -1,
|
||||
tmate_session->ssh_client.pubkey,
|
||||
strlen(tmate_session->ssh_client.pubkey) + 1);
|
||||
} else {
|
||||
proc_send(client_peer, MSG_IDENTIFY_TMATE_AUTH_NONE, -1, NULL, 0);
|
||||
}
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_TMATE_READONLY,
|
||||
-1, &tmate_session->readonly, 1);
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_TMATE_IP_ADDRESS, -1,
|
||||
tmate_session->ssh_client.ip_address,
|
||||
strlen(tmate_session->ssh_client.ip_address) + 1);
|
||||
#endif
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
|
||||
|
||||
if ((s = getenv("TERM")) == NULL)
|
||||
s = "";
|
||||
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
|
||||
@ -658,6 +662,8 @@ client_dispatch_wait(struct imsg *imsg, const char *shellcmd)
|
||||
case MSG_EXITED:
|
||||
proc_exit(client_proc);
|
||||
break;
|
||||
case MSG_TMATE_AUTH_STATUS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
#include "tmate.h"
|
||||
|
||||
/*
|
||||
* Set an option.
|
||||
@ -113,6 +114,11 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
else
|
||||
valstr = args->argv[1];
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
if (!args_has(args, 'u'))
|
||||
tmate_hook_set_option(optstr, valstr);
|
||||
#endif
|
||||
|
||||
/* Is this a user option? */
|
||||
if (*optstr == '@')
|
||||
return (cmd_set_option_user(self, cmdq, optstr, valstr));
|
||||
|
@ -266,7 +266,9 @@ server_client_lost(struct client *c)
|
||||
|
||||
server_client_unref(c);
|
||||
|
||||
#ifndef TMATE_SLAVE
|
||||
server_add_accept(0); /* may be more file descriptors now */
|
||||
#endif
|
||||
|
||||
recalculate_sizes();
|
||||
server_check_unattached();
|
||||
@ -1057,6 +1059,11 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
if (c->flags & CLIENT_DEAD)
|
||||
return;
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
if (c->flags & CLIENT_EXIT)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (imsg == NULL) {
|
||||
server_client_lost(c);
|
||||
return;
|
||||
@ -1065,6 +1072,24 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
data = imsg->data;
|
||||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_IDENTIFY_TMATE_IP_ADDRESS:
|
||||
case MSG_IDENTIFY_TMATE_AUTH_NONE:
|
||||
case MSG_IDENTIFY_TMATE_AUTH_PUBKEY:
|
||||
case MSG_IDENTIFY_TMATE_READONLY:
|
||||
server_client_dispatch_identify(c, imsg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(c->flags & CLIENT_TMATE_AUTHENTICATED)) {
|
||||
control_write(c, "Authentication needed");
|
||||
tmate_warn("Dropping unauthenticated client");
|
||||
c->flags |= CLIENT_EXIT;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_IDENTIFY_FLAGS:
|
||||
case MSG_IDENTIFY_TERM:
|
||||
@ -1074,13 +1099,18 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
case MSG_IDENTIFY_ENVIRON:
|
||||
case MSG_IDENTIFY_CLIENTPID:
|
||||
case MSG_IDENTIFY_DONE:
|
||||
#ifdef TMATE_SLAVE
|
||||
case MSG_IDENTIFY_TMATE_IP_ADDRESS:
|
||||
case MSG_IDENTIFY_TMATE_PUBKEY:
|
||||
case MSG_IDENTIFY_TMATE_READONLY:
|
||||
#endif
|
||||
server_client_dispatch_identify(c, imsg);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
if (!(c->flags & CLIENT_IDENTIFIED)) {
|
||||
tmate_warn("dropping unidentified client message: %d", imsg->hdr.type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_COMMAND:
|
||||
server_client_dispatch_command(c, imsg);
|
||||
break;
|
||||
@ -1205,6 +1235,15 @@ error:
|
||||
c->flags |= CLIENT_EXIT;
|
||||
}
|
||||
|
||||
static void handle_tmate_auth(struct client *c)
|
||||
{
|
||||
bool allow = tmate_allow_auth(c->pubkey);
|
||||
if (allow)
|
||||
c->flags |= CLIENT_TMATE_AUTHENTICATED;
|
||||
|
||||
proc_send(c->peer, MSG_TMATE_AUTH_STATUS, -1, &allow, sizeof(allow));
|
||||
}
|
||||
|
||||
/* Handle identify message. */
|
||||
void
|
||||
server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
@ -1275,11 +1314,19 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
fatalx("bad MSG_IDENTIFY_TMATE_IP_ADDRESS string");
|
||||
c->ip_address = xstrdup(data);
|
||||
break;
|
||||
case MSG_IDENTIFY_TMATE_PUBKEY:
|
||||
|
||||
case MSG_IDENTIFY_TMATE_AUTH_NONE:
|
||||
assert(!c->pubkey);
|
||||
handle_tmate_auth(c);
|
||||
break;
|
||||
|
||||
case MSG_IDENTIFY_TMATE_AUTH_PUBKEY:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_TMATE_PUBKEY string");
|
||||
c->pubkey = xstrdup(data);
|
||||
handle_tmate_auth(c);
|
||||
break;
|
||||
|
||||
case MSG_IDENTIFY_TMATE_READONLY:
|
||||
if (datalen != 1)
|
||||
fatalx("bad MSG_IDENTIFY_TMATE_READONLY size");
|
||||
@ -1370,6 +1417,9 @@ server_client_push_stdout(struct client *c)
|
||||
struct msg_stdout_data data;
|
||||
size_t sent, left;
|
||||
|
||||
if (!(c->flags & CLIENT_TMATE_AUTHENTICATED))
|
||||
return;
|
||||
|
||||
left = EVBUFFER_LENGTH(c->stdout_data);
|
||||
while (left != 0) {
|
||||
sent = left;
|
||||
@ -1411,6 +1461,9 @@ server_client_push_stderr(struct client *c)
|
||||
struct msg_stderr_data data;
|
||||
size_t sent, left;
|
||||
|
||||
if (!(c->flags & CLIENT_TMATE_AUTHENTICATED))
|
||||
return;
|
||||
|
||||
if (c->stderr_data == c->stdout_data) {
|
||||
server_client_push_stdout(c);
|
||||
return;
|
||||
|
5
server.c
5
server.c
@ -190,9 +190,8 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
|
||||
|
||||
#ifndef TMATE_SLAVE
|
||||
status_prompt_load_history();
|
||||
#endif
|
||||
|
||||
server_add_accept(0);
|
||||
#endif
|
||||
|
||||
proc_loop(server_proc, server_loop);
|
||||
#ifndef TMATE_SLAVE
|
||||
@ -379,6 +378,7 @@ server_signal(int sig)
|
||||
case SIGCHLD:
|
||||
server_child_signal();
|
||||
break;
|
||||
#ifndef TMATE_SLAVE
|
||||
case SIGUSR1:
|
||||
event_del(&server_ev_accept);
|
||||
fd = server_create_socket();
|
||||
@ -389,6 +389,7 @@ server_signal(int sig)
|
||||
}
|
||||
server_add_accept(0);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
225
tmate-auth-keys.c
Normal file
225
tmate-auth-keys.c
Normal file
@ -0,0 +1,225 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "tmate.h"
|
||||
|
||||
static void reset_and_enable_authorized_keys(void)
|
||||
{
|
||||
ssh_key *keys = tmate_session->authorized_keys;
|
||||
if (keys) {
|
||||
for (ssh_key *k = keys; *k; k++)
|
||||
ssh_key_free(*k);
|
||||
free(keys);
|
||||
}
|
||||
|
||||
keys = xreallocarray(NULL, sizeof(ssh_key), 1);
|
||||
keys[0] = NULL;
|
||||
|
||||
tmate_session->authorized_keys = keys;
|
||||
}
|
||||
|
||||
static ssh_key import_ssh_pubkey64(const char *_keystr)
|
||||
{
|
||||
/* key is formatted as "type base64_key" */
|
||||
|
||||
char * const keystr = xstrdup(_keystr);
|
||||
char *s = keystr;
|
||||
ssh_key ret = NULL;
|
||||
|
||||
char *key_type = strsep(&s, " ");
|
||||
char *key_content = strsep(&s, " ");
|
||||
|
||||
if (!key_content)
|
||||
goto out;
|
||||
|
||||
enum ssh_keytypes_e type = ssh_key_type_from_name(key_type);
|
||||
if (type == SSH_KEYTYPE_UNKNOWN)
|
||||
goto out;
|
||||
|
||||
if (ssh_pki_import_pubkey_base64(key_content, type, &ret) != SSH_OK) {
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
free(keystr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_num_authorized_keys(ssh_key *keys)
|
||||
{
|
||||
if (!keys)
|
||||
return 0;
|
||||
|
||||
int count = 0;
|
||||
for (ssh_key *k = keys; *k; k++)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void append_authorized_key(const char *keystr)
|
||||
{
|
||||
if (!tmate_session->authorized_keys)
|
||||
reset_and_enable_authorized_keys();
|
||||
|
||||
ssh_key pkey = import_ssh_pubkey64(keystr);
|
||||
if (!pkey)
|
||||
return;
|
||||
|
||||
ssh_key *keys = tmate_session->authorized_keys;
|
||||
int count = get_num_authorized_keys(keys);
|
||||
keys = xreallocarray(keys, sizeof(ssh_key), count+2);
|
||||
tmate_session->authorized_keys = keys;
|
||||
|
||||
keys[count++] = pkey;
|
||||
keys[count] = NULL;
|
||||
}
|
||||
|
||||
static void tmate_set(char *key, char *value)
|
||||
{
|
||||
if (!strcmp(key, "authorized_keys"))
|
||||
append_authorized_key(value);
|
||||
}
|
||||
|
||||
void tmate_hook_set_option(const char *name, const char *val)
|
||||
{
|
||||
if (!strcmp(name, "tmate-authorized-keys")) {
|
||||
reset_and_enable_authorized_keys();
|
||||
} else if (!strcmp(name, "tmate-set")) {
|
||||
char *key_value = xstrdup(val);
|
||||
char *s = key_value;
|
||||
|
||||
char *key = strsep(&s, "=");
|
||||
char *value = s;
|
||||
if (value)
|
||||
tmate_set(key, value);
|
||||
|
||||
free(key_value);
|
||||
}
|
||||
}
|
||||
|
||||
bool tmate_allow_auth(const char *pubkey)
|
||||
{
|
||||
/*
|
||||
* Note that we don't accept connections on the tmux socket until we
|
||||
* get the tmate ready message.
|
||||
*/
|
||||
if (!tmate_session->authorized_keys)
|
||||
return true;
|
||||
|
||||
if (!pubkey)
|
||||
return false;
|
||||
|
||||
ssh_key client_pkey = import_ssh_pubkey64(pubkey);
|
||||
if (!client_pkey)
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
for (ssh_key *k = tmate_session->authorized_keys; *k; k++) {
|
||||
if (!ssh_key_cmp(client_pkey, *k, SSH_KEY_CMP_PUBLIC)) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ssh_key_free(client_pkey);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write_all(int fd, const char *buf, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len;) {
|
||||
size_t ret = write(fd, buf+i, len-i);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
i += ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_all(int fd, char *buf, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len;) {
|
||||
size_t ret = read(fd, buf+i, len-i);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
i += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following is executed in the context of the SSH server
|
||||
*/
|
||||
bool would_tmate_session_allow_auth(const char *token, const char *pubkey)
|
||||
{
|
||||
/*
|
||||
* The existance of this function is a bit unpleasant:
|
||||
* In order to have the right SSH public key from the SSH client,
|
||||
* we need to ask the tmate session for a match. Denying the key
|
||||
* to the SSH client will make it cycle through its keys.
|
||||
* We briefly connect to the session to get an answer.
|
||||
*
|
||||
* Note that the client will get reauthenticated later (see
|
||||
* server-client.c when identifying the client).
|
||||
*/
|
||||
int sock_fd = -1;
|
||||
int ret = true;
|
||||
|
||||
if (tmate_validated_session_token(token) < 0)
|
||||
goto out;
|
||||
|
||||
char *sock_path = get_socket_path(token);
|
||||
|
||||
struct sockaddr_un sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sun_family = AF_UNIX;
|
||||
size_t size = strlcpy(sa.sun_path, sock_path, sizeof(sa.sun_path));
|
||||
free(sock_path);
|
||||
if (size >= sizeof sa.sun_path)
|
||||
goto out;
|
||||
|
||||
sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock_fd < 0)
|
||||
goto out;
|
||||
|
||||
if (connect(sock_fd, (struct sockaddr *)&sa, sizeof sa) == -1)
|
||||
goto out;
|
||||
|
||||
struct imsg_hdr hdr = {
|
||||
.type = pubkey ? MSG_IDENTIFY_TMATE_AUTH_PUBKEY :
|
||||
MSG_IDENTIFY_TMATE_AUTH_NONE,
|
||||
.len = IMSG_HEADER_SIZE + (pubkey ? strlen(pubkey)+1 : 0),
|
||||
.flags = 0,
|
||||
.peerid = PROTOCOL_VERSION,
|
||||
.pid = -1,
|
||||
};
|
||||
|
||||
if (write_all(sock_fd, (void*)&hdr, sizeof(hdr)) < 0)
|
||||
goto out;
|
||||
|
||||
if (pubkey) {
|
||||
if (write_all(sock_fd, pubkey, strlen(pubkey)+1) < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct {
|
||||
struct imsg_hdr hdr;
|
||||
bool allow;
|
||||
} __packed recv_msg;
|
||||
|
||||
if (read_all(sock_fd, (void*)&recv_msg, sizeof(recv_msg)) < 0)
|
||||
goto out;
|
||||
|
||||
if (recv_msg.hdr.type == MSG_TMATE_AUTH_STATUS &&
|
||||
recv_msg.hdr.len == sizeof(recv_msg))
|
||||
ret = recv_msg.allow;
|
||||
|
||||
tmate_info("(preauth) allow=%d", ret);
|
||||
|
||||
out:
|
||||
if (sock_fd != -1)
|
||||
close(sock_fd);
|
||||
return ret;
|
||||
}
|
@ -6,15 +6,29 @@
|
||||
|
||||
char *tmate_left_status, *tmate_right_status;
|
||||
|
||||
static void tmate_ready(struct tmate_session *session,
|
||||
__unused struct tmate_unpacker *uk)
|
||||
{
|
||||
/* This message is also used by the websocket server */
|
||||
|
||||
/*
|
||||
* We only start accepting connections once the host is ready, this
|
||||
* way we have the authorized keys loaded correctly
|
||||
*/
|
||||
|
||||
if (session->authorized_keys) {
|
||||
int count = get_num_authorized_keys(session->authorized_keys);
|
||||
tmate_info("Restricting ssh access, num_keys=%d", count);
|
||||
}
|
||||
server_add_accept(0);
|
||||
}
|
||||
|
||||
static void tmate_header(struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
{
|
||||
char *ssh_conn_str;
|
||||
|
||||
session->client_protocol_version = unpack_int(uk);
|
||||
if (session->client_protocol_version <= 4) {
|
||||
session->daemon_encoder.mpac_version = 4;
|
||||
}
|
||||
|
||||
if (session->client_protocol_version >= 3) {
|
||||
session->client_version = unpack_string(uk);
|
||||
@ -22,6 +36,15 @@ static void tmate_header(struct tmate_session *session,
|
||||
session->client_version = xstrdup("1.8.5");
|
||||
}
|
||||
|
||||
if (session->client_protocol_version < 6) {
|
||||
/* older clients don't send a ready message */
|
||||
tmate_ready(session, NULL);
|
||||
}
|
||||
|
||||
if (session->client_protocol_version < 5) {
|
||||
session->daemon_encoder.mpac_version = 4;
|
||||
}
|
||||
|
||||
tmate_notice("Daemon header: client version: %s, protocol version: %d",
|
||||
session->client_version, session->client_protocol_version);
|
||||
|
||||
@ -45,13 +68,6 @@ static void tmate_header(struct tmate_session *session,
|
||||
tmate_send_client_ready();
|
||||
}
|
||||
|
||||
static void tmate_ready(__unused struct tmate_session *session,
|
||||
__unused struct tmate_unpacker *uk)
|
||||
{
|
||||
/* used by the websocket */
|
||||
}
|
||||
|
||||
|
||||
extern u_int next_window_pane_id;
|
||||
|
||||
static void tmate_sync_window_panes(struct window *w,
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "tmate.h"
|
||||
#include "tmate-protocol.h"
|
||||
|
||||
#define pack(what, ...) _pack(&tmate_session->daemon_encoder, what, __VA_ARGS__)
|
||||
#define pack(what, ...) _pack(&tmate_session->daemon_encoder, what, ##__VA_ARGS__)
|
||||
|
||||
static void __tmate_notify(const char *msg)
|
||||
{
|
||||
|
@ -127,7 +127,7 @@ static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
|
||||
|
||||
static int auth_pubkey_cb(__unused ssh_session session,
|
||||
const char *user,
|
||||
struct ssh_key_struct *pubkey,
|
||||
ssh_key pubkey,
|
||||
char signature_state, void *userdata)
|
||||
{
|
||||
struct tmate_ssh_client *client = userdata;
|
||||
@ -135,9 +135,24 @@ static int auth_pubkey_cb(__unused ssh_session session,
|
||||
switch (signature_state) {
|
||||
case SSH_PUBLICKEY_STATE_VALID:
|
||||
client->username = xstrdup(user);
|
||||
if (ssh_pki_export_pubkey_base64(pubkey, &client->pubkey) != SSH_OK)
|
||||
|
||||
const char *key_type = ssh_key_type_to_char(ssh_key_type(pubkey));
|
||||
|
||||
char *b64_key;
|
||||
if (ssh_pki_export_pubkey_base64(pubkey, &b64_key) != SSH_OK)
|
||||
tmate_fatal("error getting public key");
|
||||
|
||||
char *pubkey64;
|
||||
xasprintf(&pubkey64, "%s %s", key_type, b64_key);
|
||||
free(b64_key);
|
||||
|
||||
if (!would_tmate_session_allow_auth(user, pubkey64)) {
|
||||
free(pubkey64);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
client->pubkey = pubkey64;
|
||||
|
||||
return SSH_AUTH_SUCCESS;
|
||||
case SSH_PUBLICKEY_STATE_NONE:
|
||||
return SSH_AUTH_SUCCESS;
|
||||
@ -146,14 +161,15 @@ static int auth_pubkey_cb(__unused ssh_session session,
|
||||
}
|
||||
}
|
||||
|
||||
static int auth_none_cb(ssh_session session, const char *user, void *userdata)
|
||||
static int auth_none_cb(__unused ssh_session session, const char *user, void *userdata)
|
||||
{
|
||||
(void)session;
|
||||
|
||||
struct tmate_ssh_client *client = userdata;
|
||||
|
||||
if (!would_tmate_session_allow_auth(user, NULL))
|
||||
return SSH_AUTH_DENIED;
|
||||
|
||||
client->username = xstrdup(user);
|
||||
client->pubkey = xstrdup("none");
|
||||
client->pubkey = NULL;
|
||||
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
@ -16,7 +16,14 @@
|
||||
|
||||
#define CONTROL_PROTOCOL_VERSION 2
|
||||
|
||||
#define pack(what, ...) _pack(&tmate_session->websocket_encoder, what, __VA_ARGS__)
|
||||
#define pack(what, ...) _pack(&tmate_session->websocket_encoder, what, ##__VA_ARGS__)
|
||||
|
||||
#define pack_string_or_nil(str) ({ \
|
||||
if (str) \
|
||||
pack(string, str); \
|
||||
else \
|
||||
pack(nil); \
|
||||
})
|
||||
|
||||
static void ctl_daemon_fwd_msg(__unused struct tmate_session *session,
|
||||
struct tmate_unpacker *uk)
|
||||
@ -205,7 +212,7 @@ void tmate_websocket_exec(struct tmate_session *session, const char *command)
|
||||
pack(int, TMATE_CTL_EXEC);
|
||||
pack(string, client->username);
|
||||
pack(string, client->ip_address);
|
||||
pack(string, client->pubkey);
|
||||
pack_string_or_nil(client->pubkey);
|
||||
pack(string, command);
|
||||
}
|
||||
|
||||
@ -223,7 +230,7 @@ void tmate_notify_client_join(__unused struct tmate_session *session,
|
||||
pack(int, TMATE_CTL_CLIENT_JOIN);
|
||||
pack(int, c->id);
|
||||
pack(string, c->ip_address);
|
||||
pack(string, c->pubkey);
|
||||
pack_string_or_nil(c->pubkey);
|
||||
pack(boolean, c->readonly);
|
||||
}
|
||||
|
||||
@ -270,7 +277,7 @@ void tmate_send_websocket_header(struct tmate_session *session)
|
||||
pack(int, TMATE_CTL_HEADER);
|
||||
pack(int, CONTROL_PROTOCOL_VERSION);
|
||||
pack(string, session->ssh_client.ip_address);
|
||||
pack(string, session->ssh_client.pubkey);
|
||||
pack_string_or_nil(session->ssh_client.pubkey);
|
||||
pack(string, session->session_token);
|
||||
pack(string, session->session_token_ro);
|
||||
|
||||
|
10
tmate.h
10
tmate.h
@ -33,6 +33,12 @@ extern void printflike(2, 3) tmate_log(int level, const char *msg, ...);
|
||||
exit(1); \
|
||||
})
|
||||
|
||||
/* tmate-auth-keys.c */
|
||||
extern void tmate_hook_set_option(const char *name, const char *val);
|
||||
extern bool tmate_allow_auth(const char *pubkey);
|
||||
extern bool would_tmate_session_allow_auth(const char *token, const char *pubkey);
|
||||
extern int get_num_authorized_keys(ssh_key *keys);
|
||||
|
||||
/* tmate-msgpack.c */
|
||||
|
||||
typedef void tmate_encoder_write_cb(void *userdata, struct evbuffer *buffer);
|
||||
@ -57,7 +63,7 @@ extern void msgpack_pack_boolean(msgpack_packer *pk, bool value);
|
||||
extern int _msgpack_pack_object(msgpack_packer *pk, msgpack_object d);
|
||||
#define msgpack_pack_object _msgpack_pack_object
|
||||
|
||||
#define _pack(enc, what, ...) msgpack_pack_##what(&(enc)->pk, __VA_ARGS__)
|
||||
#define _pack(enc, what, ...) msgpack_pack_##what(&(enc)->pk, ##__VA_ARGS__)
|
||||
|
||||
struct tmate_unpacker;
|
||||
struct tmate_decoder;
|
||||
@ -222,6 +228,8 @@ struct tmate_session {
|
||||
int tmux_socket_fd;
|
||||
|
||||
/* only for role deamon */
|
||||
ssh_key *authorized_keys; /* array with NULL as last element */
|
||||
|
||||
const char *session_token;
|
||||
const char *session_token_ro;
|
||||
const char *obfuscated_session_token; /* for logging purposes */
|
||||
|
15
tmux.h
15
tmux.h
@ -414,13 +414,6 @@ enum msgtype {
|
||||
MSG_IDENTIFY_CLIENTPID,
|
||||
MSG_IDENTIFY_CWD,
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
/* Next time put this after TMATE_LATENCY */
|
||||
MSG_IDENTIFY_TMATE_IP_ADDRESS,
|
||||
MSG_IDENTIFY_TMATE_PUBKEY,
|
||||
MSG_IDENTIFY_TMATE_READONLY,
|
||||
#endif
|
||||
|
||||
MSG_COMMAND = 200,
|
||||
MSG_DETACH,
|
||||
MSG_DETACHKILL,
|
||||
@ -440,7 +433,12 @@ enum msgtype {
|
||||
MSG_WAKEUP,
|
||||
|
||||
#ifdef TMATE_SLAVE
|
||||
MSG_LATENCY = 300
|
||||
MSG_LATENCY = 300,
|
||||
MSG_IDENTIFY_TMATE_IP_ADDRESS,
|
||||
MSG_IDENTIFY_TMATE_AUTH_NONE,
|
||||
MSG_IDENTIFY_TMATE_AUTH_PUBKEY,
|
||||
MSG_IDENTIFY_TMATE_READONLY,
|
||||
MSG_TMATE_AUTH_STATUS,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -1307,6 +1305,7 @@ struct client {
|
||||
#define CLIENT_STATUSFORCE 0x80000
|
||||
#ifdef TMATE_SLAVE
|
||||
#define CLIENT_TMATE_NOTIFIED_JOIN 0x10000000
|
||||
#define CLIENT_TMATE_AUTHENTICATED 0x20000000
|
||||
#endif
|
||||
int flags;
|
||||
struct key_table *keytable;
|
||||
|
Loading…
x
Reference in New Issue
Block a user