Skip to content
Snippets Groups Projects
Commit b5ae6469 authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

More transport work.

Next step is to implement a KEX.
parent 2315671e
Branches
Tags
No related merge requests found
Pipeline #7328 passed
......@@ -5,7 +5,22 @@
#include "ssh.h"
#include "ssh-trans.h"
typedef struct deuce_ssh_transport_global_config {
atomic_bool used;
const char *software_version;
const char *version_comment;
size_t kex_entries;
char **kex_name;
deuce_ssh_kex_handler_t *kex_handler;
deuce_ssh_kex_cleanup_t *kex_cleanup;
int (*tx)(uint8_t *buf, size_t bufsz, atomic_bool *terminate, void *cbdata);
int (*rx)(uint8_t *buf, size_t bufsz, atomic_bool *terminate, void *cbdata);
int (*rx_line)(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminate, void *cbdata);
int (*extra_line_cb)(uint8_t *buf, size_t bufsz, void *cbdata);
} *deuce_ssh_transport_global_config_t;
static const char * const sw_ver = "DeuceSSH-0.0";
static struct deuce_ssh_transport_global_config gconf;
static inline bool
has_nulls(uint8_t *buf, size_t buflen)
......@@ -53,7 +68,7 @@ version_ex(deuce_ssh_session_t sess)
uint8_t line[256];
while (!sess->terminate) {
res = sess->rx_line(line, sizeof(line) - 1, &received, &sess->terminate, sess->rx_line_cbdata);
res = gconf.rx_line(line, sizeof(line) - 1, &received, &sess->terminate, sess->rx_line_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
......@@ -83,9 +98,9 @@ version_ex(deuce_ssh_session_t sess)
assert(res == thrd_success);
return 0;
}
if (sess->extra_line_cb) {
if (gconf.extra_line_cb) {
line[received] = 0;
res = sess->extra_line_cb(line, received, sess->extra_line_cbdata);
res = gconf.extra_line_cb(line, received, sess->extra_line_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
......@@ -122,38 +137,38 @@ tx_handshake(void *arg)
{
deuce_ssh_session_t sess = arg;
int res;
uint8_t line[255];
size_t sz = 0;
/* Handshake */
res = sess->tx((uint8_t *)"SSH-2.0-", 8, &sess->terminate, sess->tx_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
memcpy(line, "SSH-2.0-", 8);
sz += 8;
size_t asz = strlen(gconf.software_version);
memcpy(&line[sz], gconf.software_version, asz);
sz += asz;
if (gconf.version_comment != NULL) {
memcpy(&line[sz], " ", 1);
sz += 1;
asz = strlen(gconf.version_comment);
memcpy(&line[sz], gconf.version_comment, asz);
sz += asz;
}
size_t sz = strlen(sess->software_version);
res = sess->tx((uint8_t *)sess->software_version, sz, &sess->terminate, sess->tx_cbdata);
res = gconf.tx(line, sz, &sess->terminate, sess->tx_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
}
if (sess->version_comment != NULL) {
res = sess->tx((uint8_t *)" ", 1, &sess->terminate, sess->tx_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
}
sz = strlen(sess->version_comment);
res = sess->tx((uint8_t *)sess->software_version, sz, &sess->terminate, sess->tx_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
}
}
return 0;
}
void
deuce_ssh_transport_cleanup(deuce_ssh_session_t sess)
{
if (sess->trans->kex_selected != SIZE_MAX) {
if (gconf.kex_cleanup[sess->trans->kex_selected] != NULL)
gconf.kex_cleanup[sess->trans->kex_selected](sess);
sess->trans->kex_selected = SIZE_MAX;
}
free(sess->remote_software_version);
sess->remote_software_version = NULL;
free(sess->remote_version_comment);
......@@ -163,9 +178,13 @@ deuce_ssh_transport_cleanup(deuce_ssh_session_t sess)
int
deuce_ssh_transport_init(deuce_ssh_session_t sess)
{
if (sess->software_version == NULL)
sess->software_version = sw_ver;
gconf.used = true;
if (gconf.software_version == NULL)
gconf.software_version = sw_ver;
sess->trans = calloc(1, sizeof(struct deuce_ssh_transport_state));
if (sess->trans == NULL)
return DEUCE_SSH_ERROR_ALLOC;
thrd_t thrd;
if (thrd_create(&thrd, rx_thread, sess) != thrd_success)
return DEUCE_SSH_ERROR_INIT;
......@@ -176,7 +195,55 @@ deuce_ssh_transport_init(deuce_ssh_session_t sess)
thrd_join(thrd, &tres);
return res;
}
sess->trans->kex_selected = SIZE_MAX;
sess->trans->kex_state = 0;
sess->trans->transport_thread = thrd;
return 0;
}
int
deuce_ssh_transport_register_kex(const char *name, deuce_ssh_kex_handler_t kex_handler, deuce_ssh_kex_cleanup_t kex_cleanup)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (gconf.kex_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
char **newnames = realloc(gconf.kex_name, sizeof(gconf.kex_name[0]) * (gconf.kex_entries + 1));
if (newnames == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.kex_name = newnames;
gconf.kex_name[gconf.kex_entries] = strdup(name);
deuce_ssh_kex_handler_t *newhandlers = realloc(gconf.kex_handler, sizeof(gconf.kex_handler[0]) * (gconf.kex_entries + 1));
if (newhandlers == NULL) {
free(gconf.kex_name[gconf.kex_entries]);
return DEUCE_SSH_ERROR_ALLOC;
}
gconf.kex_handler = newhandlers;
gconf.kex_handler[gconf.kex_entries] = kex_handler;
deuce_ssh_kex_cleanup_t *newcleanup = realloc(gconf.kex_cleanup, sizeof(gconf.kex_cleanup[0]) * (gconf.kex_entries + 1));
if (newcleanup == NULL) {
free(gconf.kex_name[gconf.kex_entries]);
return DEUCE_SSH_ERROR_ALLOC;
}
gconf.kex_cleanup = newcleanup;
gconf.kex_cleanup[gconf.kex_entries] = kex_cleanup;
gconf.kex_entries++;
return 0;
}
int
deuce_ssh_transport_set_callbacks(deuce_ssh_transport_io_cb_t tx, deuce_ssh_transport_io_cb_t rx, deuce_ssh_transport_rxline_cb_t rx_line, deuce_ssh_transport_extra_line_cb_t extra_line_cb)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
gconf.tx = tx;
gconf.rx = rx;
gconf.rx_line = rx_line;
gconf.extra_line_cb = extra_line_cb;
sess->transport_thread = thrd;
return 0;
}
// RFC-4253
#include "ssh.h"
#include "ssh-arch.h"
#ifndef DEUCE_SSH_TRANS_H
......@@ -33,19 +34,41 @@
#define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14
#define SSH_DISCONNECT_ILLEGAL_USER_NAME 15
struct deuce_ssh_transport_packet {
typedef struct deuce_ssh_transport_packet {
deuce_ssh_string_t payload;
deuce_ssh_string_t random_padding;
deuce_ssh_string_t mac;
deuce_ssh_uint32_t packet_length;
deuce_ssh_byte_t padding;
};
} *deuce_ssh_transport_packet_t;
struct deuce_ssh_transport_state {
typedef int (*deuce_ssh_kex_handler_t)(deuce_ssh_transport_packet_t pkt, deuce_ssh_session_t sess);
typedef void (*deuce_ssh_kex_cleanup_t)(deuce_ssh_session_t sess);
typedef struct deuce_ssh_transport_state {
uint32_t tx_seq;
uint32_t rx_seq;
bool client;
};
/* Transport options */
thrd_t transport_thread;
/* KEX options */
void *kex_cbdata;
uint32_t kex_state;
size_t kex_selected;
/* KEX outputs */
size_t shared_secret_sz;
uint8_t *shared_secret;
size_t exchange_hash_sz;
uint8_t *exchange_hash;
size_t enc_selected;
size_t mac_selected;
size_t comp_selected;
} *deuce_ssh_transport_state_t;
int deuce_ssh_transport_init(deuce_ssh_session_t sess);
void deuce_ssh_transport_cleanup(deuce_ssh_session_t sess);
......
......@@ -9,9 +9,8 @@ deuce_ssh_session_init(deuce_ssh_session_t sess)
return DEUCE_SSH_ERROR_INIT;
res = deuce_ssh_transport_init(sess);
if (res < 0) {
if (res < 0)
return res;
}
sess->initialized = true;
return 0;
......@@ -24,7 +23,7 @@ deuce_ssh_session_terminate(deuce_ssh_session_t sess)
if (atomic_compare_exchange_strong(&sess->initialized, &t, false)) {
sess->terminate = true;
int tres;
thrd_join(sess->transport_thread, &tres);
thrd_join(sess->trans->transport_thread, &tres);
sess->terminate = false;
return true;
}
......
......@@ -20,6 +20,13 @@ _Static_assert(0, "threads.h support required");
#define DEUCE_SSH_ERROR_ALLOC -3
#define DEUCE_SSH_ERROR_INIT -4
#define DEUCE_SSH_ERROR_TERMINATED -5
#define DEUCE_SSH_ERROR_TOOLATE -6
#define DEUCE_SSH_ERROR_TOOMANY -7
typedef struct deuce_ssh_transport_state *deuce_ssh_transport_state_t;
typedef int (*deuce_ssh_transport_io_cb_t)(uint8_t *buf, size_t bufsz, atomic_bool *terminate, void *cbdata);
typedef int (*deuce_ssh_transport_rxline_cb_t)(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminate, void *cbdata);
typedef int (*deuce_ssh_transport_extra_line_cb_t)(uint8_t *buf, size_t bufsz, void *cbdata);
typedef struct deuce_ssh_session {
/* Global */
......@@ -27,22 +34,16 @@ typedef struct deuce_ssh_session {
atomic_bool initialized;
atomic_bool terminate;
/* Transport options */
const char *software_version;
const char *version_comment;
/* Transport Remote information */
char *remote_software_version;
char *remote_version_comment;
void *tx_cbdata;
int (*tx)(uint8_t *buf, size_t bufsz, atomic_bool *terminate, void *cbdata);
void *rx_cbdata;
int (*rx)(uint8_t *buf, size_t bufsz, atomic_bool *terminate, void *cbdata);
void *rx_line_cbdata;
int (*rx_line)(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminate, void *cbdata);
void *extra_line_cbdata;
int (*extra_line_cb)(uint8_t *buf, size_t bufsz, void *cbdata);
thrd_t transport_thread;
/* Transport Remote information */
char *remote_software_version;
char *remote_version_comment;
deuce_ssh_transport_state_t trans;
} *deuce_ssh_session_t;
int deuce_ssh_session_init(deuce_ssh_session_t sess);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment