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
No related branches found
No related tags found
No related merge requests found
#include "ssh-trans.h" #include "deucessh.h"
static int static int
compress(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess) compress(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess)
......
...@@ -14,16 +14,17 @@ _Static_assert(0, "threads.h support required"); ...@@ -14,16 +14,17 @@ _Static_assert(0, "threads.h support required");
#include <stdbool.h> #include <stdbool.h>
#include <threads.h> #include <threads.h>
#define DEUCE_SSH_ERROR_NONE 0 #define DEUCE_SSH_ERROR_NONE 0
#define DEUCE_SSH_ERROR_PARSE -1 #define DEUCE_SSH_ERROR_PARSE -1
#define DEUCE_SSH_ERROR_INVALID -2 #define DEUCE_SSH_ERROR_INVALID -2
#define DEUCE_SSH_ERROR_ALLOC -3 #define DEUCE_SSH_ERROR_ALLOC -3
#define DEUCE_SSH_ERROR_INIT -4 #define DEUCE_SSH_ERROR_INIT -4
#define DEUCE_SSH_ERROR_TERMINATED -5 #define DEUCE_SSH_ERROR_TERMINATED -5
#define DEUCE_SSH_ERROR_TOOLATE -6 #define DEUCE_SSH_ERROR_TOOLATE -6
#define DEUCE_SSH_ERROR_TOOMANY -7 #define DEUCE_SSH_ERROR_TOOMANY -7
#define DEUCE_SSH_ERROR_TOOLONG -8 #define DEUCE_SSH_ERROR_TOOLONG -8
#define DEUCE_SSH_ERROR_MUST_BE_NULL -9 #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 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_io_cb_t)(uint8_t *buf, size_t bufsz, atomic_bool *terminate, void *cbdata);
......
#include "ssh-trans.h" #include "deucessh.h"
static int static int
encrypt(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess) encrypt(uint8_t *buf, uint8_t *bufsz, deuce_ssh_session_t sess)
......
#include "ssh-trans.h" #include "deucessh.h"
static int static int
generate(uint8_t *key, uint8_t *buf, size_t bufsz, uint8_t *outbuf, deuce_ssh_session_t sess) 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) ...@@ -40,8 +40,10 @@ deuce_ssh_parse_boolean(uint8_t * buf, size_t bufsz, deuce_ssh_boolean_t *val)
assert(bufsz >= 1); assert(bufsz >= 1);
if (bufsz < 1) if (bufsz < 1)
return DEUCE_SSH_ERROR_PARSE; return DEUCE_SSH_ERROR_PARSE;
#ifdef PARANOID_WRONG
if (buf[0] != 0 && buf[0] != 1) if (buf[0] != 0 && buf[0] != 1)
return DEUCE_SSH_ERROR_INVALID; return DEUCE_SSH_ERROR_INVALID;
#endif
*val = buf[0]; *val = buf[0];
return 1; return 1;
} }
...@@ -119,7 +121,7 @@ deuce_ssh_serialize_uint64(deuce_ssh_uint64_t val, uint8_t *buf, MAYBE_UNUSED si ...@@ -119,7 +121,7 @@ deuce_ssh_serialize_uint64(deuce_ssh_uint64_t val, uint8_t *buf, MAYBE_UNUSED si
} }
ssize_t 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; ssize_t ret;
uint32_t len; uint32_t len;
...@@ -127,7 +129,6 @@ deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val) ...@@ -127,7 +129,6 @@ deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val)
size_t pos = 0; size_t pos = 0;
assert(bufsz >= 4); assert(bufsz >= 4);
assert(*val == NULL);
if (bufsz < 4) if (bufsz < 4)
return DEUCE_SSH_ERROR_PARSE; return DEUCE_SSH_ERROR_PARSE;
ret = deuce_ssh_parse_uint32(buf, bufsz, &len); 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) ...@@ -138,13 +139,8 @@ deuce_ssh_parse_string(uint8_t * buf, size_t bufsz, deuce_ssh_string_t *val)
assert(bufsz >= sz); assert(bufsz >= sz);
if (bufsz < sz) if (bufsz < sz)
return DEUCE_SSH_ERROR_PARSE; return DEUCE_SSH_ERROR_PARSE;
*val = malloc(sz); val->length = len;
if (*val == NULL) memcpy(&val->value, &buf[ret], len);
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);
return sz; return sz;
} }
...@@ -164,129 +160,83 @@ deuce_ssh_serialize_string(deuce_ssh_string_t val, uint8_t *buf, MAYBE_UNUSED si ...@@ -164,129 +160,83 @@ deuce_ssh_serialize_string(deuce_ssh_string_t val, uint8_t *buf, MAYBE_UNUSED si
} }
ssize_t 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; ssize_t ret = deuce_ssh_parse_string(buf, bufsz, val);
uint32_t len; if (val->value[0] == val->value[1])
size_t sz; return DEUCE_SSH_ERROR_INVALID;
size_t pos = 0; if ((val->value[0] == 0) && ((val->value[0] & 0x80) == 0))
return DEUCE_SSH_ERROR_INVALID;
assert(bufsz >= 4); if ((val->value[0] == 255) && (val->value[0] & 0x80))
assert(*val == NULL); return DEUCE_SSH_ERROR_INVALID;
if (bufsz < 4) return ret;
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;
} }
size_t size_t
deuce_ssh_serialized_mpint_length(deuce_ssh_mpint_t val) deuce_ssh_serialized_mpint_length(deuce_ssh_mpint_t val)
{ {
int ret = BN_bn2mpi(val, NULL); return val->length + 4;
assert(ret >= 4);
return ret;
} }
void void
deuce_ssh_serialize_mpint(deuce_ssh_mpint_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos) deuce_ssh_serialize_mpint(deuce_ssh_mpint_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos)
{ {
assert(*pos + 4 <= bufsz); deuce_ssh_serialize_string(val, buf, bufsz, pos);
*pos += BN_bn2mpi(val, &buf[*pos]);
} }
ssize_t 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; struct deuce_ssh_string str;
size_t names = 0;
assert(*val == NULL);
ssize_t ret = deuce_ssh_parse_string(buf, bufsz, &str); ssize_t ret = deuce_ssh_parse_string(buf, bufsz, &str);
if (ret < 4) if (ret < 4)
return ret; return ret;
if (str->length > 0) { if (str.length > 0) {
names++; for (uint32_t i = 0; i < str.length; i++) {
for (size_t i = 0; i < str->length; i++) { if (str.value[i] == ',') {
if (str->value[i] == ',') { if (i == 0 || str.value[i - 1] == ',')
if (i == 0 || str->value[i - 1] == ',') {
free(str);
return DEUCE_SSH_ERROR_PARSE; return DEUCE_SSH_ERROR_PARSE;
}
names++;
} }
if (str->value[i] < ' ') { if (str.value[i] < ' ')
free(str);
return DEUCE_SSH_ERROR_PARSE; return DEUCE_SSH_ERROR_PARSE;
} if (str.value[i] > '~')
if (str->value[i] > '~') {
free(str);
return DEUCE_SSH_ERROR_PARSE; 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; return ret;
} }
size_t size_t
deuce_ssh_serialized_namelist_length(deuce_ssh_namelist_t val) deuce_ssh_serialized_namelist_length(deuce_ssh_namelist_t val)
{ {
size_t ret = 4; return val->length + 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;
} }
void void
deuce_ssh_serialize_namelist(deuce_ssh_namelist_t val, uint8_t *buf, MAYBE_UNUSED size_t bufsz, size_t *pos) 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; ssize_t
size_t lpos = *pos; deuce_ssh_parse_namelist_next(deuce_ssh_string_t val, deuce_ssh_namelist_t nl)
*pos += 4; {
uint8_t *data = (uint8_t *)&val->name[0]; if (nl->next >= nl->length)
size_t names = 0; return DEUCE_SSH_ERROR_NOMORE;
for (size_t i = 0;; i++) { val->value = &(nl->value[nl->next]);
if (data[i] == 0) { for (val->length = 0; nl->next < nl->length; nl->next++, val->length++) {
names++; if (nl->value[nl->next] == ',') {
if (names == val->names) nl->next++;
break; 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; ...@@ -20,13 +20,14 @@ typedef bool deuce_ssh_boolean_t;
typedef uint32_t deuce_ssh_uint32_t; typedef uint32_t deuce_ssh_uint32_t;
typedef uint64_t deuce_ssh_uint64_t; typedef uint64_t deuce_ssh_uint64_t;
typedef struct deuce_ssh_string { typedef struct deuce_ssh_string {
deuce_ssh_byte_t *value;
deuce_ssh_uint32_t length; deuce_ssh_uint32_t length;
deuce_ssh_byte_t value[];
} *deuce_ssh_string_t; } *deuce_ssh_string_t;
typedef BIGNUM *deuce_ssh_mpint_t; typedef struct deuce_ssh_string *deuce_ssh_mpint_t;
typedef struct deuce_ssh_namelist { typedef struct deuce_ssh_namelist {
size_t names; deuce_ssh_byte_t *value;
uint8_t *name[]; deuce_ssh_uint32_t length;
deuce_ssh_uint32_t next;
} *deuce_ssh_namelist_t; } *deuce_ssh_namelist_t;
#define deuce_ssh_parse(buf, bufsz, val) _Generic(val, \ #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 * ...@@ -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); 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); 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); 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); 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); 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); 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); 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); 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 #endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment