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

Allow connections based on authorized_keys file.

When run with option `-a /path/to/authorized_keys`, tmate-slave will only
authenticate public keys present in the file `/path/to/authorized_keys`.

The expected format is the same as specified in sshd(8) manpage, section
"AUTHORIZED_KEYS FILE FORMAT".

See: tmate-io/tmate-slave#37

Closes #38
This commit is contained in:
Reinaldo de Souza Junior 2017-11-13 14:49:15 -02:00 committed by Nicolas Viennot
parent 76ec591e91
commit d6a76e0609
3 changed files with 73 additions and 11 deletions

View File

@ -34,6 +34,7 @@ extern int client_connect(struct event_base *base, const char *path, int start_s
struct tmate_settings _tmate_settings = { struct tmate_settings _tmate_settings = {
.keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR, .keys_dir = TMATE_SSH_DEFAULT_KEYS_DIR,
.authorized_keys_path = NULL,
.ssh_port = TMATE_SSH_DEFAULT_PORT, .ssh_port = TMATE_SSH_DEFAULT_PORT,
.proxy_hostname = NULL, .proxy_hostname = NULL,
.bind_addr = NULL, .bind_addr = NULL,
@ -102,7 +103,7 @@ void request_server_termination(void)
static void usage(void) static void usage(void)
{ {
fprintf(stderr, "usage: tmate-slave [-b ip] [-h hostname] [-k keys_dir] [-p port] [-x proxy_hostname] [-q proxy_port] [-s] [-v]\n"); fprintf(stderr, "usage: tmate-slave [-b ip] [-h hostname] [-k keys_dir] [-a authorized_keys_path] [-p port] [-x proxy_hostname] [-q proxy_port] [-s] [-v]\n");
} }
static char* get_full_hostname(void) static char* get_full_hostname(void)
@ -155,7 +156,7 @@ int main(int argc, char **argv, char **envp)
{ {
int opt; int opt;
while ((opt = getopt(argc, argv, "b:h:k:p:x:q:sv")) != -1) { while ((opt = getopt(argc, argv, "b:h:k:a:p:x:q:sv")) != -1) {
switch (opt) { switch (opt) {
case 'b': case 'b':
tmate_settings->bind_addr = xstrdup(optarg); tmate_settings->bind_addr = xstrdup(optarg);
@ -166,6 +167,9 @@ int main(int argc, char **argv, char **envp)
case 'k': case 'k':
tmate_settings->keys_dir = xstrdup(optarg); tmate_settings->keys_dir = xstrdup(optarg);
break; break;
case 'a':
tmate_settings->authorized_keys_path = xstrdup(optarg);
break;
case 'p': case 'p':
tmate_settings->ssh_port = atoi(optarg); tmate_settings->ssh_port = atoi(optarg);
break; break;

View File

@ -4,6 +4,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <event.h> #include <event.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -106,6 +107,61 @@ static ssh_channel channel_open_request_cb(ssh_session session, void *userdata)
return client->channel; return client->channel;
} }
static int check_authorized_keys(struct ssh_key_struct *client_pubkey) {
#define MAX_PUBKEY_SIZE 0x4000
const char *authorized_keys_path = tmate_settings->authorized_keys_path;
const char *token_delim = " ";
FILE *file;
char key_buf[MAX_PUBKEY_SIZE], *key_type, *key_content;
enum ssh_keytypes_e type;
ssh_key pkey;
if (authorized_keys_path == NULL)
return SSH_AUTH_SUCCESS;
file = fopen(authorized_keys_path, "rb");
if (file == NULL) {
tmate_fatal("Could not open authorized_keys file: \"%s\"", authorized_keys_path);
return SSH_AUTH_DENIED;
}
while (fgets(key_buf, MAX_PUBKEY_SIZE, file)) {
if (key_buf[0] == '#' || key_buf[0] == '\0')
continue;
key_type = strtok(key_buf, token_delim);
if (key_type == NULL)
continue;
type = ssh_key_type_from_name(key_type);
if (type == SSH_KEYTYPE_UNKNOWN)
continue;
key_content = strtok(NULL, token_delim);
if (key_content == NULL)
continue;
pkey = ssh_key_new();
if (ssh_pki_import_pubkey_base64(key_content, type, &pkey) != SSH_OK) {
ssh_key_free(pkey);
continue;
}
if (!ssh_key_cmp(pkey, client_pubkey, SSH_KEY_CMP_PUBLIC)) {
ssh_key_free(pkey);
fclose(file);
return SSH_AUTH_SUCCESS;
}
ssh_key_free(pkey);
}
fclose(file);
return SSH_AUTH_DENIED;
}
static int auth_pubkey_cb(__unused ssh_session session, static int auth_pubkey_cb(__unused ssh_session session,
const char *user, const char *user,
struct ssh_key_struct *pubkey, struct ssh_key_struct *pubkey,
@ -118,7 +174,8 @@ static int auth_pubkey_cb(__unused ssh_session session,
client->username = xstrdup(user); client->username = xstrdup(user);
if (ssh_pki_export_pubkey_base64(pubkey, &client->pubkey) != SSH_OK) if (ssh_pki_export_pubkey_base64(pubkey, &client->pubkey) != SSH_OK)
tmate_fatal("error getting public key"); tmate_fatal("error getting public key");
return SSH_AUTH_SUCCESS;
return check_authorized_keys(pubkey);
case SSH_PUBLICKEY_STATE_NONE: case SSH_PUBLICKEY_STATE_NONE:
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
default: default:

View File

@ -205,6 +205,7 @@ extern void tmate_ssh_server_main(struct tmate_session *session,
struct tmate_settings { struct tmate_settings {
const char *keys_dir; const char *keys_dir;
const char *authorized_keys_path;
int ssh_port; int ssh_port;
const char *proxy_hostname; const char *proxy_hostname;
int proxy_port; int proxy_port;