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

Remove the expectation of dynamic memory in parsing packets

The expectation is now that there will be a single copy of SSH BPP
contents and arrays and buffers will be pointers into that.
parent 2ae025dc
Branches
Tags
No related merge requests found
#include "ssh-trans.h"
#include "deucessh.h"
static int
compress(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess)
......
......@@ -24,6 +24,7 @@ _Static_assert(0, "threads.h support required");
#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);
......
#include "ssh-trans.h"
#include "deucessh.h"
static int
encrypt(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess)
......
#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)
......
......@@ -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)
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;
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;
}
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)
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;
}
......@@ -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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment