diff --git a/src/ssh/comp/none.c b/src/ssh/comp/none.c index 7d040934e6031bcebfe02842f081421ded767dfd..912b89609648126a2b8add4457aecb8468df3162 100644 --- a/src/ssh/comp/none.c +++ b/src/ssh/comp/none.c @@ -1,4 +1,4 @@ -#include "ssh-trans.h" +#include "deucessh.h" static int compress(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess) diff --git a/src/ssh/deucessh.h b/src/ssh/deucessh.h index eb1985c2f26020ce887c4138923231b54564d86c..ad6db796feb13ca52252476c7168a1ef51cd0ebc 100644 --- a/src/ssh/deucessh.h +++ b/src/ssh/deucessh.h @@ -14,16 +14,17 @@ _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_MUST_BE_NULL -9 +#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 +#define DEUCE_SSH_ERROR_NOMORE -10 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); diff --git a/src/ssh/enc/none.c b/src/ssh/enc/none.c index d4dad104397b0943be44f64437bfa07134ad4aa7..7d5ec2611eaa622b634da0ce9be22063cd1cd6ee 100644 --- a/src/ssh/enc/none.c +++ b/src/ssh/enc/none.c @@ -1,4 +1,4 @@ -#include "ssh-trans.h" +#include "deucessh.h" static int encrypt(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess) diff --git a/src/ssh/mac/none.c b/src/ssh/mac/none.c index 914573292a868d7ce890ed7defca8175675f830d..5ae2c18e402ac60c6b6c770d2c21de3ae3e5cdcc 100644 --- a/src/ssh/mac/none.c +++ b/src/ssh/mac/none.c @@ -1,4 +1,4 @@ -#include "ssh-trans.h" +#include "deucessh.h" static int generate(uint8_t *key, uint8_t *buf, size_t bufsz, uint8_t *outbuf, deuce_ssh_session_t sess) diff --git a/src/ssh/ssh-arch.c b/src/ssh/ssh-arch.c index 8dc7e1d5a785dd1a4ac3b422a11e8f03a63a39f9..8c2a34c8cc2fa788ba4fc41f221e314bdba2ac8c 100644 --- a/src/ssh/ssh-arch.c +++ b/src/ssh/ssh-arch.c @@ -40,8 +40,10 @@ deuce_ssh_parse_boolean(uint8_t * buf, size_t bufsz, deuce_ssh_boolean_t *val) assert(bufsz >= 1); if (bufsz < 1) return DEUCE_SSH_ERROR_PARSE; +#ifdef PARANOID_WRONG if (buf[0] != 0 && buf[0] != 1) return DEUCE_SSH_ERROR_INVALID; +#endif *val = buf[0]; return 1; } @@ -119,7 +121,7 @@ deuce_ssh_serialize_uint64(deuce_ssh_uint64_t val, uint8_t *buf, MAYBE_UNUSED si } ssize_t -deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val) +deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t val) { ssize_t ret; uint32_t len; @@ -127,7 +129,6 @@ deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val) size_t pos = 0; assert(bufsz >= 4); - assert(*val == NULL); if (bufsz < 4) return DEUCE_SSH_ERROR_PARSE; ret = deuce_ssh_parse_uint32(buf, bufsz, &len); @@ -138,13 +139,8 @@ deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val) assert(bufsz >= sz); if (bufsz < sz) return DEUCE_SSH_ERROR_PARSE; - *val = malloc(sz); - if (*val == NULL) - return DEUCE_SSH_ERROR_ALLOC; - (*val)->length = len; - deuce_ssh_serialize_uint32(len, (uint8_t *)*val, sz, &pos); - assert(pos == 4); - memcpy(&(*val)->value, &buf[pos], len); + val->length = len; + memcpy(&val->value, &buf[ret], len); return sz; } @@ -164,129 +160,83 @@ deuce_ssh_serialize_string(deuce_ssh_string_t val, uint8_t *buf, MAYBE_UNUSED si } ssize_t -deuce_ssh_parse_mpint(uint8_t * buf, size_t bufsz, deuce_ssh_mpint_t *val) +deuce_ssh_parse_mpint(uint8_t * buf, size_t bufsz, deuce_ssh_mpint_t val) { - size_t ret; - uint32_t len; - size_t sz; - size_t pos = 0; - - assert(bufsz >= 4); - assert(*val == NULL); - if (bufsz < 4) - return DEUCE_SSH_ERROR_PARSE; - ret = deuce_ssh_parse_uint32(buf, bufsz, &len); - if (ret < 4) - return ret; - assert(ret == 4); - sz = ret + len; - assert(bufsz >= sz); - if (bufsz < sz) - return DEUCE_SSH_ERROR_PARSE; - *val = BN_mpi2bn(buf, sz, NULL); - return sz; + ssize_t ret = deuce_ssh_parse_string(buf, bufsz, val); + if (val->value[0] == val->value[1]) + return DEUCE_SSH_ERROR_INVALID; + if ((val->value[0] == 0) && ((val->value[0] & 0x80) == 0)) + return DEUCE_SSH_ERROR_INVALID; + if ((val->value[0] == 255) && (val->value[0] & 0x80)) + return DEUCE_SSH_ERROR_INVALID; + return ret; } size_t deuce_ssh_serialized_mpint_length(deuce_ssh_mpint_t val) { - int ret = BN_bn2mpi(val, NULL); - assert(ret >= 4); - return ret; + return val->length + 4; } void deuce_ssh_serialize_mpint(deuce_ssh_mpint_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos) { - assert(*pos + 4 <= bufsz); - *pos += BN_bn2mpi(val, &buf[*pos]); + deuce_ssh_serialize_string(val, buf, bufsz, pos); } ssize_t -deuce_ssh_parse_namelist(uint8_t * buf, size_t bufsz, deuce_ssh_namelist_t *val) +deuce_ssh_parse_namelist(uint8_t * buf, size_t bufsz, deuce_ssh_namelist_t val) { - deuce_ssh_string_t str = NULL; - size_t names = 0; + struct deuce_ssh_string str; - assert(*val == NULL); ssize_t ret = deuce_ssh_parse_string(buf, bufsz, &str); if (ret < 4) return ret; - if (str->length > 0) { - names++; - for (size_t i = 0; i < str->length; i++) { - if (str->value[i] == ',') { - if (i == 0 || str->value[i - 1] == ',') { - free(str); + if (str.length > 0) { + for (uint32_t i = 0; i < str.length; i++) { + if (str.value[i] == ',') { + if (i == 0 || str.value[i - 1] == ',') return DEUCE_SSH_ERROR_PARSE; - } - names++; } - if (str->value[i] < ' ') { - free(str); + if (str.value[i] < ' ') return DEUCE_SSH_ERROR_PARSE; - } - if (str->value[i] > '~') { - free(str); + if (str.value[i] > '~') return DEUCE_SSH_ERROR_PARSE; - } - } - } - size_t lsz = sizeof(uint8_t *) * names; - *val = malloc(offsetof(struct deuce_ssh_namelist, name) + lsz + str->length + (names == 0 ? 0 : 1)); - if (*val == NULL) { - free(str); - return DEUCE_SSH_ERROR_ALLOC; - } - (*val)->names = names; - if (names > 0) { - uint8_t *data = (uint8_t *)&(*val)->name[names]; - memcpy(data, str->value, str->length); - data[str->length] = ','; - uint8_t *end = data; - size_t remain = str->length + 1; - for (size_t i = 0; i < names; i++) { - (*val)->name[i] = end; - end = memchr(end, ',', remain); - assert(end); - assert(*end == ','); - *end = 0; - end++; - remain = (str->length + 1) - (end - data); } } + val->value = str.value; + val->length = str.length; + val->next = 0; return ret; } size_t deuce_ssh_serialized_namelist_length(deuce_ssh_namelist_t val) { - size_t ret = 4; - for (size_t i = 0; i < val->names; i++) { - ret += strlen((char *)val->name[i]); - if (i < (val->names - 1)) - ret += 1; - } - return ret; + return val->length + 4; } void deuce_ssh_serialize_namelist(deuce_ssh_namelist_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos) { - assert(bufsz >= 4); + struct deuce_ssh_string str = { + .value = val->value, + .length = val->length, + }; + deuce_ssh_serialize_string(&str, buf, bufsz, pos); +} - uint8_t *lbuf = buf; - size_t lpos = *pos; - *pos += 4; - uint8_t *data = (uint8_t *)&val->name[0]; - size_t names = 0; - for (size_t i = 0;; i++) { - if (data[i] == 0) { - names++; - if (names == val->names) - break; +ssize_t +deuce_ssh_parse_namelist_next(deuce_ssh_string_t val, deuce_ssh_namelist_t nl) +{ + if (nl->next >= nl->length) + return DEUCE_SSH_ERROR_NOMORE; + val->value = &(nl->value[nl->next]); + for (val->length = 0; nl->next < nl->length; nl->next++, val->length++) { + if (nl->value[nl->next] == ',') { + nl->next++; + break; } - buf[(*pos)++] = data[i]; } - deuce_ssh_serialize_uint32(*pos - lpos - 4, lbuf, 4, &lpos); + return val->length + 4; } diff --git a/src/ssh/ssh-arch.h b/src/ssh/ssh-arch.h index ca844688dd2dcb2044150d846e8fecbc18e9da38..17b1cc46e4913ae447896c4f9f1b8d22fbeea837 100644 --- a/src/ssh/ssh-arch.h +++ b/src/ssh/ssh-arch.h @@ -20,13 +20,14 @@ typedef bool deuce_ssh_boolean_t; typedef uint32_t deuce_ssh_uint32_t; typedef uint64_t deuce_ssh_uint64_t; typedef struct deuce_ssh_string { + deuce_ssh_byte_t *value; deuce_ssh_uint32_t length; - deuce_ssh_byte_t value[]; } *deuce_ssh_string_t; -typedef BIGNUM *deuce_ssh_mpint_t; +typedef struct deuce_ssh_string *deuce_ssh_mpint_t; typedef struct deuce_ssh_namelist { - size_t names; - uint8_t *name[]; + deuce_ssh_byte_t *value; + deuce_ssh_uint32_t length; + deuce_ssh_uint32_t next; } *deuce_ssh_namelist_t; #define deuce_ssh_parse(buf, bufsz, val) _Generic(val, \ @@ -72,16 +73,17 @@ ssize_t deuce_ssh_parse_uint64(uint8_t * buf, size_t bufsz, deuce_ssh_uint64_t * size_t deuce_ssh_serialized_uint64_length(deuce_ssh_uint64_t val); void deuce_ssh_serialize_uint64(deuce_ssh_uint64_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos); -ssize_t deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val); +ssize_t deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t val); size_t deuce_ssh_serialized_string_length(deuce_ssh_string_t val); void deuce_ssh_serialize_string(deuce_ssh_string_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos); -ssize_t deuce_ssh_parse_mpint(uint8_t * buf, size_t bufsz, deuce_ssh_mpint_t *val); +ssize_t deuce_ssh_parse_mpint(uint8_t * buf, size_t bufsz, deuce_ssh_mpint_t val); size_t deuce_ssh_serialized_mpint_length(deuce_ssh_mpint_t val); void deuce_ssh_serialize_mpint(deuce_ssh_mpint_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos); -ssize_t deuce_ssh_parse_namelist(uint8_t * buf, size_t bufsz, deuce_ssh_namelist_t *val); +ssize_t deuce_ssh_parse_namelist(uint8_t * buf, size_t bufsz, deuce_ssh_namelist_t val); size_t deuce_ssh_serialized_namelist_length(deuce_ssh_namelist_t val); void deuce_ssh_serialize_namelist(deuce_ssh_namelist_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos); +ssize_t deuce_ssh_parse_namelist_next(deuce_ssh_string_t val, deuce_ssh_namelist_t nl); #endif