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

Eliminate egregious and unneeded allocations.

parent 76b6856b
No related branches found
No related tags found
No related merge requests found
Pipeline #7349 passed
......@@ -129,8 +129,9 @@ rxline(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminat
{
size_t pos = 0;
bool lastcr = false;
int ret = 0;
for (;;) {
while (!(*terminate)) {
int res = rx(&buf[pos], 1, terminate, cbdata);
if (res < 0)
return res;
......@@ -138,11 +139,14 @@ rxline(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminat
lastcr = true;
if (buf[pos] == '\n' && lastcr) {
*bytes_received = pos + 1;
return 0;
return ret;
}
if (pos + 1 < bufsz)
pos++;
else
ret = DEUCE_SSH_ERROR_TOOLONG;
}
return DEUCE_SSH_ERROR_TERMINATED;
}
static int
......
......@@ -16,49 +16,34 @@ typedef struct deuce_ssh_transport_global_config {
int (*extra_line_cb)(uint8_t *buf, size_t bufsz, void *cbdata);
size_t kex_entries;
char **kex_name;
uint32_t *kex_flags;
deuce_ssh_kex_handler_t *kex_handler;
deuce_ssh_kex_cleanup_t *kex_cleanup;
deuce_ssh_kex_t kex_head;
deuce_ssh_kex_t kex_tail;
size_t key_algo_entries;
char **key_algo_name;
uint32_t *key_algo_flags;
deuce_ssh_key_algo_sign_t *key_algo_sign;
deuce_ssh_key_algo_haskey_t *key_algo_haskey;
deuce_ssh_key_algo_cleanup_t *key_algo_cleanup;
deuce_ssh_key_algo_t key_algo_head;
deuce_ssh_key_algo_t key_algo_tail;
size_t enc_entries;
char **enc_name;
uint32_t *enc_flags;
uint16_t *enc_blocksize;
uint16_t *enc_key_size;
deuce_ssh_enc_encrypt_t *enc_encrypt;
deuce_ssh_enc_decrypt_t *enc_decrypt;
deuce_ssh_enc_cleanup_t *enc_cleanup;
deuce_ssh_enc_t enc_head;
deuce_ssh_enc_t enc_tail;
size_t mac_entries;
char **mac_name;
uint16_t *mac_digest_size;
uint16_t *mac_key_size;
deuce_ssh_mac_generate_t *mac_generate;
deuce_ssh_mac_cleanup_t *mac_cleanup;
deuce_ssh_mac_t mac_head;
deuce_ssh_mac_t mac_tail;
size_t comp_entries;
char **comp_name;
uint32_t *comp_flags;
uint16_t *comp_blocksize;
uint16_t *comp_key_size;
deuce_ssh_comp_compress_t *comp_compress;
deuce_ssh_comp_uncompress_t *comp_uncompress;
deuce_ssh_comp_cleanup_t *comp_cleanup;
deuce_ssh_comp_t comp_head;
deuce_ssh_comp_t comp_tail;
size_t lang_entries;
char **lang_name;
deuce_ssh_language_t lang_head;
deuce_ssh_language_t lang_tail;
} *deuce_ssh_transport_global_config_t;
static const char * const sw_ver = "DeuceSSH-0.0";
static struct deuce_ssh_transport_global_config gconf;
static uint8_t tx_packet[SSH_TOTAL_BPP_PACKET_SIZE_MAX];
static uint8_t rx_packet[SSH_TOTAL_BPP_PACKET_SIZE_MAX];
static inline bool
has_nulls(uint8_t *buf, size_t buflen)
......@@ -89,56 +74,35 @@ is_20(uint8_t *buf, size_t buflen)
return (buf[4] == '2' && buf[5] == '.' && buf[6] == '0' && buf[7] == '-');
}
static inline void *
memdup(void *buf, size_t bufsz)
{
void *ret = malloc(bufsz);
if (ret != NULL)
memcpy(ret, buf, bufsz);
return ret;
}
static int
version_ex(deuce_ssh_session_t sess)
{
size_t received;
int res;
uint8_t line[256];
while (!sess->terminate) {
res = gconf.rx_line(line, sizeof(line) - 1, &received, &sess->terminate, sess->rx_line_cbdata);
res = gconf.rx_line(rx_packet, sizeof(rx_packet) - 1, &received, &sess->terminate, sess->rx_line_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
}
if (is_version_line(line, received)) {
if (has_nulls(line,received) || missing_crlf(line, received) || !is_20(line, received)) {
if (is_version_line(rx_packet, received)) {
if (received > 255 || has_nulls(rx_packet, received) || missing_crlf(rx_packet, received) || !is_20(rx_packet, received)) {
sess->terminate = true;
return DEUCE_SSH_ERROR_INVALID;
}
uint8_t *sp = memchr(line, ' ', received);
char *c = NULL;
char *v;
if (sp != NULL) {
c = memdup(&sp[1], received - 3 - (sp - line));
v = memdup(&line[8], (sp - line) - 9);
}
else {
v = memdup(&line[8], received - 10);
}
res = mtx_lock(&sess->mtx);
free(sess->remote_software_version);
free(sess->remote_version_comment);
assert(res == thrd_success);
sess->remote_software_version = v;
sess->remote_version_comment = c;
sess->remote_software_id_string_sz = received - 2;
memcpy(sess->remote_software_id_string, rx_packet, sess->remote_software_id_string_sz);
sess->remote_software_id_string[sess->remote_software_id_string_sz] = 0;
res = mtx_unlock(&sess->mtx);
assert(res == thrd_success);
return 0;
}
if (gconf.extra_line_cb) {
line[received] = 0;
res = gconf.extra_line_cb(line, received, sess->extra_line_cbdata);
rx_packet[received] = 0;
res = gconf.extra_line_cb(rx_packet, received, sess->extra_line_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
......@@ -161,7 +125,6 @@ rx_thread(void *arg)
while (!sess->terminate) {
// Read enough to get the length
// Allocate space for packet
// Read the rest of the packet
// Decrypt
// Decompress
......@@ -175,29 +138,31 @@ tx_handshake(void *arg)
{
deuce_ssh_session_t sess = arg;
int res;
uint8_t line[255];
size_t sz = 0;
/* Handshake */
memcpy(line, "SSH-2.0-", 8);
memcpy(tx_packet, "SSH-2.0-", 8);
sz += 8;
size_t asz = strlen(gconf.software_version);
if (sz + asz + 2 > 255)
return DEUCE_SSH_ERROR_TOOLONG;
memcpy(&line[sz], gconf.software_version, asz);
memcpy(&tx_packet[sz], gconf.software_version, asz);
sz += asz;
if (gconf.version_comment != NULL) {
memcpy(&line[sz], " ", 1);
memcpy(&tx_packet[sz], " ", 1);
sz += 1;
asz = strlen(gconf.version_comment);
if (sz + asz + 2 > 255)
return DEUCE_SSH_ERROR_TOOLONG;
memcpy(&line[sz], gconf.version_comment, asz);
memcpy(&tx_packet[sz], gconf.version_comment, asz);
sz += asz;
}
memcpy(&line[sz], "\r\n", 2);
memcpy(sess->trans->id_str, tx_packet, sz);
sess->trans->id_str_sz = sz;
sess->trans->id_str[sz] = 0;
memcpy(&tx_packet[sz], "\r\n", 2);
sz += 2;
res = gconf.tx(line, sz, &sess->terminate, sess->tx_cbdata);
res = gconf.tx(tx_packet, sz, &sess->terminate, sess->tx_cbdata);
if (res < 0) {
sess->terminate = true;
return res;
......@@ -208,35 +173,34 @@ tx_handshake(void *arg)
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;
if (sess->trans->kex_selected) {
if (sess->trans->kex_selected->cleanup != NULL)
sess->trans->kex_selected->cleanup(sess);
sess->trans->kex_selected = NULL;
}
if (sess->trans->key_algo_selected != SIZE_MAX) {
if (gconf.key_algo_cleanup[sess->trans->key_algo_selected] != NULL)
gconf.key_algo_cleanup[sess->trans->key_algo_selected](sess);
sess->trans->key_algo_selected = SIZE_MAX;
if (sess->trans->key_algo_selected) {
if (sess->trans->key_algo_selected->cleanup != NULL)
sess->trans->key_algo_selected->cleanup(sess);
sess->trans->key_algo_selected = NULL;
}
if (sess->trans->enc_selected != SIZE_MAX) {
if (gconf.enc_cleanup[sess->trans->enc_selected] != NULL)
gconf.enc_cleanup[sess->trans->enc_selected](sess);
sess->trans->enc_selected = SIZE_MAX;
if (sess->trans->enc_selected) {
if (sess->trans->enc_selected->cleanup != NULL)
sess->trans->enc_selected->cleanup(sess);
sess->trans->enc_selected = NULL;
}
if (sess->trans->mac_selected != SIZE_MAX) {
if (gconf.mac_cleanup[sess->trans->mac_selected] != NULL)
gconf.mac_cleanup[sess->trans->mac_selected](sess);
sess->trans->mac_selected = SIZE_MAX;
if (sess->trans->mac_selected) {
if (sess->trans->mac_selected->cleanup != NULL)
sess->trans->mac_selected->cleanup(sess);
sess->trans->mac_selected = NULL;
}
if (sess->trans->comp_selected != SIZE_MAX) {
if (gconf.comp_cleanup[sess->trans->comp_selected] != NULL)
gconf.comp_cleanup[sess->trans->comp_selected](sess);
sess->trans->comp_selected = SIZE_MAX;
if (sess->trans->comp_selected) {
if (sess->trans->comp_selected->cleanup != NULL)
sess->trans->comp_selected->cleanup(sess);
sess->trans->comp_selected = NULL;
}
free(sess->remote_software_version);
sess->remote_software_version = NULL;
free(sess->remote_version_comment);
sess->remote_version_comment = NULL;
sess->remote_software_id_string_sz = 0;
sess->remote_software_id_string[0] = 0;
if (sess->remote_languages) {
for (size_t i = 0; sess->remote_languages[i]; i++)
free(sess->remote_languages[i]);
......@@ -265,251 +229,120 @@ deuce_ssh_transport_init(deuce_ssh_session_t sess)
thrd_join(thrd, &tres);
return res;
}
sess->trans->kex_selected = SIZE_MAX;
sess->trans->key_algo_selected = SIZE_MAX;
sess->trans->kex_selected = NULL;
sess->trans->key_algo_selected = NULL;
sess->trans->enc_selected = NULL;
sess->trans->mac_selected = NULL;
sess->trans->comp_selected = NULL;
sess->trans->transport_thread = thrd;
return 0;
}
int
deuce_ssh_transport_register_kex(const char *name, uint32_t kex_flags, deuce_ssh_kex_handler_t kex_handler, deuce_ssh_kex_cleanup_t kex_cleanup)
deuce_ssh_transport_register_kex(deuce_ssh_kex_t kex)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (kex->next)
return DEUCE_SSH_ERROR_MUST_BE_NULL;
if (gconf.kex_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
if (gconf.kex_head == NULL)
gconf.kex_head = kex;
if (gconf.kex_tail != NULL)
gconf.kex_tail->next = kex;
gconf.kex_tail = kex;
uint32_t *newflags = realloc(gconf.kex_flags, sizeof(gconf.kex_flags[0]) * (gconf.kex_entries + 1));
if (newflags == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.kex_flags = newflags;
gconf.kex_flags[gconf.kex_entries] = kex_flags;
deuce_ssh_kex_handler_t *newhandlers = realloc(gconf.kex_handler, sizeof(gconf.kex_handler[0]) * (gconf.kex_entries + 1));
if (newhandlers == NULL)
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)
return DEUCE_SSH_ERROR_ALLOC;
gconf.kex_cleanup = newcleanup;
gconf.kex_cleanup[gconf.kex_entries] = kex_cleanup;
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);
if (gconf.kex_name[gconf.kex_entries] == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.kex_entries++;
return 0;
}
int
deuce_ssh_transport_register_key_algo(const char *name, uint32_t key_algo_flags, deuce_ssh_key_algo_sign_t key_algo_sign, deuce_ssh_key_algo_haskey_t key_algo_haskey, deuce_ssh_key_algo_cleanup_t key_algo_cleanup)
deuce_ssh_transport_register_key_algo(deuce_ssh_key_algo_t key_algo)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (key_algo->next)
return DEUCE_SSH_ERROR_MUST_BE_NULL;
if (gconf.key_algo_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
if (gconf.key_algo_head == NULL)
gconf.key_algo_head = key_algo;
if (gconf.key_algo_tail != NULL)
gconf.key_algo_tail->next = key_algo;
gconf.key_algo_tail = key_algo;
uint32_t *newflags = realloc(gconf.key_algo_flags, sizeof(gconf.key_algo_flags[0]) * (gconf.key_algo_entries + 1));
if (newflags == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.key_algo_flags = newflags;
gconf.key_algo_flags[gconf.key_algo_entries] = key_algo_flags;
deuce_ssh_key_algo_sign_t *newsigns = realloc(gconf.key_algo_sign, sizeof(gconf.key_algo_sign[0]) * (gconf.key_algo_entries + 1));
if (newsigns == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.key_algo_sign = newsigns;
gconf.key_algo_sign[gconf.key_algo_entries] = key_algo_sign;
deuce_ssh_key_algo_haskey_t *newhaskeys = realloc(gconf.key_algo_haskey, sizeof(gconf.key_algo_haskey[0]) * (gconf.key_algo_entries + 1));
if (newhaskeys == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.key_algo_haskey = newhaskeys;
gconf.key_algo_haskey[gconf.key_algo_entries] = key_algo_haskey;
deuce_ssh_key_algo_cleanup_t *newcleanup = realloc(gconf.key_algo_cleanup, sizeof(gconf.key_algo_cleanup[0]) * (gconf.key_algo_entries + 1));
if (newcleanup == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.key_algo_cleanup = newcleanup;
gconf.key_algo_cleanup[gconf.key_algo_entries] = key_algo_cleanup;
char **newnames = realloc(gconf.key_algo_name, sizeof(gconf.key_algo_name[0]) * (gconf.key_algo_entries + 1));
if (newnames == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.key_algo_name = newnames;
gconf.key_algo_name[gconf.key_algo_entries] = strdup(name);
if (gconf.key_algo_name[gconf.key_algo_entries] == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.key_algo_entries++;
return 0;
}
int
deuce_ssh_transport_register_enc(const char *name, uint32_t enc_flags, uint16_t enc_blocksize, uint16_t enc_key_size, deuce_ssh_enc_encrypt_t enc_encrypt, deuce_ssh_enc_decrypt_t enc_decrypt, deuce_ssh_key_algo_cleanup_t enc_cleanup)
deuce_ssh_transport_register_enc(deuce_ssh_enc_t enc)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (enc->next)
return DEUCE_SSH_ERROR_MUST_BE_NULL;
if (gconf.enc_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
if (gconf.enc_head == NULL)
gconf.enc_head = enc;
if (gconf.enc_tail != NULL)
gconf.enc_tail->next = enc;
gconf.enc_tail = enc;
uint32_t *newflags = realloc(gconf.enc_flags, sizeof(gconf.enc_flags[0]) * (gconf.enc_entries + 1));
if (newflags == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_flags = newflags;
gconf.enc_flags[gconf.enc_entries] = enc_flags;
uint16_t *newbss = realloc(gconf.enc_blocksize, sizeof(gconf.enc_blocksize[0]) * (gconf.enc_entries + 1));
if (newbss == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_blocksize = newbss;
gconf.enc_blocksize[gconf.enc_entries] = enc_blocksize;
uint16_t *newkss = realloc(gconf.enc_key_size, sizeof(gconf.enc_key_size[0]) * (gconf.enc_entries + 1));
if (newkss == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_key_size = newkss;
gconf.enc_key_size[gconf.enc_entries] = enc_key_size;
deuce_ssh_enc_encrypt_t *newencrypts = realloc(gconf.enc_encrypt, sizeof(gconf.enc_encrypt[0]) * (gconf.enc_entries + 1));
if (newencrypts == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_encrypt = newencrypts;
gconf.enc_encrypt[gconf.enc_entries] = enc_encrypt;
deuce_ssh_enc_decrypt_t *newdecrypts = realloc(gconf.enc_decrypt, sizeof(gconf.enc_decrypt[0]) * (gconf.enc_entries + 1));
if (newdecrypts == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_decrypt = newdecrypts;
gconf.enc_decrypt[gconf.enc_entries] = enc_decrypt;
deuce_ssh_enc_cleanup_t *newcleanup = realloc(gconf.enc_cleanup, sizeof(gconf.enc_cleanup[0]) * (gconf.enc_entries + 1));
if (newcleanup == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_cleanup = newcleanup;
gconf.enc_cleanup[gconf.enc_entries] = enc_cleanup;
char **newnames = realloc(gconf.enc_name, sizeof(gconf.enc_name[0]) * (gconf.enc_entries + 1));
if (newnames == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_name = newnames;
gconf.enc_name[gconf.enc_entries] = strdup(name);
if (gconf.enc_name[gconf.enc_entries] == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.enc_entries++;
return 0;
}
int
deuce_ssh_transport_register_mac(const char *name, uint16_t mac_digest_size, uint16_t mac_key_size, deuce_ssh_mac_generate_t mac_generate, deuce_ssh_key_algo_cleanup_t mac_cleanup)
deuce_ssh_transport_register_mac(deuce_ssh_mac_t mac)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (mac->next)
return DEUCE_SSH_ERROR_MUST_BE_NULL;
if (gconf.mac_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
if (gconf.mac_head == NULL)
gconf.mac_head = mac;
if (gconf.mac_tail != NULL)
gconf.mac_tail->next = mac;
gconf.mac_tail = mac;
uint16_t *newdss = realloc(gconf.mac_digest_size, sizeof(gconf.mac_digest_size[0]) * (gconf.mac_entries + 1));
if (newdss == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.mac_digest_size = newdss;
gconf.mac_digest_size[gconf.mac_entries] = mac_digest_size;
uint16_t *newkss = realloc(gconf.mac_key_size, sizeof(gconf.mac_key_size[0]) * (gconf.mac_entries + 1));
if (newkss == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.mac_key_size = newkss;
gconf.mac_key_size[gconf.mac_entries] = mac_key_size;
deuce_ssh_mac_generate_t *newgens = realloc(gconf.mac_generate, sizeof(gconf.mac_generate[0]) * (gconf.mac_entries + 1));
if (newgens == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.mac_generate = newgens;
gconf.mac_generate[gconf.mac_entries] = mac_generate;
deuce_ssh_mac_cleanup_t *newcleanup = realloc(gconf.mac_cleanup, sizeof(gconf.mac_cleanup[0]) * (gconf.mac_entries + 1));
if (newcleanup == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.mac_cleanup = newcleanup;
gconf.mac_cleanup[gconf.mac_entries] = mac_cleanup;
char **newnames = realloc(gconf.mac_name, sizeof(gconf.mac_name[0]) * (gconf.mac_entries + 1));
if (newnames == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.mac_name = newnames;
gconf.mac_name[gconf.mac_entries] = strdup(name);
if (gconf.mac_name[gconf.mac_entries] == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.mac_entries++;
return 0;
}
int
deuce_ssh_transport_register_comp(const char *name, deuce_ssh_comp_compress_t comp_compress, deuce_ssh_comp_uncompress_t comp_uncompress, deuce_ssh_key_algo_cleanup_t comp_cleanup)
deuce_ssh_transport_register_comp(deuce_ssh_comp_t comp)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (comp->next)
return DEUCE_SSH_ERROR_MUST_BE_NULL;
if (gconf.comp_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
if (gconf.comp_head == NULL)
gconf.comp_head = comp;
if (gconf.comp_tail != NULL)
gconf.comp_tail->next = comp;
gconf.comp_tail = comp;
deuce_ssh_comp_compress_t *newcompress = realloc(gconf.comp_compress, sizeof(gconf.comp_compress[0]) * (gconf.comp_entries + 1));
if (newcompress == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.comp_compress = newcompress;
gconf.comp_compress[gconf.comp_entries] = comp_compress;
deuce_ssh_comp_uncompress_t *newuncompress = realloc(gconf.comp_uncompress, sizeof(gconf.comp_uncompress[0]) * (gconf.comp_entries + 1));
if (newuncompress == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.comp_uncompress = newuncompress;
gconf.comp_uncompress[gconf.comp_entries] = comp_uncompress;
deuce_ssh_comp_cleanup_t *newcleanup = realloc(gconf.comp_cleanup, sizeof(gconf.comp_cleanup[0]) * (gconf.comp_entries + 1));
if (newcleanup == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.comp_cleanup = newcleanup;
gconf.comp_cleanup[gconf.comp_entries] = comp_cleanup;
char **newnames = realloc(gconf.comp_name, sizeof(gconf.comp_name[0]) * (gconf.comp_entries + 1));
if (newnames == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.comp_name = newnames;
gconf.comp_name[gconf.comp_entries] = strdup(name);
if (gconf.comp_name[gconf.comp_entries] == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.comp_entries++;
return 0;
}
int
deuce_ssh_transport_register_lang(const char *name)
deuce_ssh_transport_register_lang(deuce_ssh_language_t lang)
{
if (gconf.used)
return DEUCE_SSH_ERROR_TOOLATE;
if (lang->next)
return DEUCE_SSH_ERROR_MUST_BE_NULL;
if (gconf.lang_entries + 1 == SIZE_MAX)
return DEUCE_SSH_ERROR_TOOMANY;
if (gconf.lang_head == NULL)
gconf.lang_head = lang;
if (gconf.lang_tail != NULL)
gconf.lang_tail->next = lang;
gconf.lang_tail = lang;
char **newnames = realloc(gconf.lang_name, sizeof(gconf.lang_name[0]) * (gconf.lang_entries + 1));
if (newnames == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.lang_name = newnames;
gconf.lang_name[gconf.lang_entries] = strdup(name);
if (gconf.lang_name[gconf.lang_entries] == NULL)
return DEUCE_SSH_ERROR_ALLOC;
gconf.lang_entries++;
return 0;
}
......
......@@ -40,6 +40,20 @@
#define DEUCE_SSH_KEY_ALGO_FLAG_ENCRYPTION_CAPABLE UINT32_C(1<<0)
#define DEUCE_SSH_KEY_ALGO_FLAG_SIGNATURE_CAPABLE UINT32_C(1<<1)
#ifndef SSH_TOTAL_BPP_PACKET_SIZE_MAX
/*
* Defined in RFC 4253 s6.1, but may be larger "where they might be needed"
* and "if the identification string indicates that the other party is able to process them"
* which means that we would need to maintain a list of implementation id
* strings that support larger packets, *and* understand which message
* "need" a larger packet.
*
* That seems like a never-ending job, so I'll just allow the user to
* override this and let them sort it out if the need to.
*/
#define SSH_TOTAL_BPP_PACKET_SIZE_MAX 35000
#endif
typedef struct deuce_ssh_transport_packet {
deuce_ssh_string_t payload;
deuce_ssh_string_t random_padding;
......@@ -66,6 +80,59 @@ typedef int (*deuce_ssh_comp_compress_t)(uint8_t *buf, uint8_t *bufsz, deuce_ssh
typedef int (*deuce_ssh_comp_uncompress_t)(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess);
typedef void (*deuce_ssh_comp_cleanup_t)(deuce_ssh_session_t sess);
typedef struct deuce_ssh_kex {
struct deuce_ssh_kex *next;
deuce_ssh_kex_handler_t handler;
deuce_ssh_kex_cleanup_t cleanup;
uint32_t flags;
char name[];
} *deuce_ssh_kex_t;
typedef struct deuce_ssh_key_algo {
struct deuce_ssh_key_algo *next;
deuce_ssh_key_algo_sign_t sign;
deuce_ssh_key_algo_haskey_t haskey;
deuce_ssh_key_algo_cleanup_t cleanup;
uint32_t flags;
char name[];
} *deuce_ssh_key_algo_t;
typedef struct deuce_ssh_enc {
struct deuce_ssh_enc *next;
deuce_ssh_enc_encrypt_t encrypt;
deuce_ssh_enc_decrypt_t decrypt;
deuce_ssh_enc_cleanup_t cleanup;
uint32_t flags;
uint16_t blocksize;
uint16_t key_size;
char name[];
} *deuce_ssh_enc_t;
typedef struct deuce_ssh_mac {
struct deuce_ssh_mac *next;
deuce_ssh_mac_generate_t generate;
deuce_ssh_mac_cleanup_t cleanup;
uint16_t *digest_size;
uint16_t *key_size;
char name[];
} *deuce_ssh_mac_t;
typedef struct deuce_ssh_comp {
struct deuce_ssh_comp *next;
deuce_ssh_comp_compress_t compress;
deuce_ssh_comp_uncompress_t uncompress;
deuce_ssh_comp_cleanup_t cleanup;
uint32_t flags;
uint16_t blocksize;
uint16_t key_size;
char name[];
} *deuce_ssh_comp_t;
typedef struct deuce_ssh_language {
struct deuce_ssh_language *next;
char name;
} *deuce_ssh_language_t;
typedef struct deuce_ssh_transport_state {
uint32_t tx_seq;
uint32_t rx_seq;
......@@ -73,10 +140,12 @@ typedef struct deuce_ssh_transport_state {
/* Transport options */
thrd_t transport_thread;
size_t id_str_sz;
char id_str[254];
/* KEX options */
void *kex_cbdata;
size_t kex_selected;
deuce_ssh_kex_t kex_selected;
/* KEX outputs */
size_t shared_secret_sz;
......@@ -84,16 +153,14 @@ typedef struct deuce_ssh_transport_state {
size_t exchange_hash_sz;
uint8_t *exchange_hash;
/* Public Key Algorithms */
void *key_algo_cbdata;
size_t key_algo_selected;
deuce_ssh_key_algo_t key_algo_selected;
void *enc_cbdata;
size_t enc_selected;
deuce_ssh_enc_t enc_selected;
void *mac_cbdata;
size_t mac_selected;
deuce_ssh_mac_t mac_selected;
void *comp_cbdata;
size_t comp_selected;
deuce_ssh_comp_t comp_selected;
} *deuce_ssh_transport_state_t;
......
......@@ -14,15 +14,16 @@ _Static_assert(0, "threads.h support required");
#include <stdbool.h>
#include <threads.h>
#define DEUCE_SSH_ERROR_NONE 0
#define DEUCE_SSH_ERROR_PARSE -1
#define DEUCE_SSH_ERROR_INVALID -2
#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
#define DEUCE_SSH_ERROR_TOOLONG -8
#define DEUCE_SSH_ERROR_NONE 0
#define DEUCE_SSH_ERROR_PARSE -1
#define DEUCE_SSH_ERROR_INVALID -2
#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
#define DEUCE_SSH_ERROR_TOOLONG -8
#define DEUCE_SSH_ERROR_MUST_BE_NULL -9
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);
......@@ -37,8 +38,8 @@ typedef struct deuce_ssh_session {
bool is_server;
/* Transport Remote information */
char *remote_software_version;
char *remote_version_comment;
size_t remote_software_id_string_sz;
char remote_software_id_string[254];
char **remote_languages;
void *tx_cbdata;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment