From 456110b0c3165498f3b2b41a0dd10c7d6769ebaa Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Wed, 9 May 2018 16:15:45 +0800 Subject: implement SSH buffer in C --- src/protocol/CMakeLists.txt | 1 + src/protocol/internal/buffer.c | 132 +++++++++++++++++++++++++++++++++++++++++ src/protocol/internal/buffer.h | 65 ++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 src/protocol/internal/buffer.c create mode 100644 src/protocol/internal/buffer.h diff --git a/src/protocol/CMakeLists.txt b/src/protocol/CMakeLists.txt index 84d53d1..7a3ad8e 100644 --- a/src/protocol/CMakeLists.txt +++ b/src/protocol/CMakeLists.txt @@ -13,6 +13,7 @@ set(export_SRCS ) set(internal_SRCS + internal/buffer.c internal/ssh_crypto_common.h internal/ssh_crypto_common.c internal/ssh_cipher.h diff --git a/src/protocol/internal/buffer.c b/src/protocol/internal/buffer.c new file mode 100644 index 0000000..388cbe0 --- /dev/null +++ b/src/protocol/internal/buffer.c @@ -0,0 +1,132 @@ +/* + * buffer.c: SSH buffer + * Copyright (C) 2018 Iru Cai + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "buffer.h" +#include + +#define INITSIZE 2048 + +int buffer_init(buffer *b) +{ + b->p = (uint8_t *)malloc(INITSIZE); + if (b->p) { + b->alloc = INITSIZE; + b->offs = 0; + b->sz = 0; + return 1; + } else { + return 0; + } +} + +static int ensure(buffer *b, size_t len) +{ + if (b->offs + b->sz + len <= b->alloc) + return 1; + + uint8_t *r = (uint8_t *)realloc(b->p, (b->alloc + len) * 2); + if (r == NULL) + return 0; + b->alloc = (b->alloc + len) * 2; + b->p = r; + return 1; +} + +int buffer_append(buffer *b, const uint8_t *s, size_t len) +{ + if (ensure(b, len)) { + memcpy(b->p + b->offs + b->sz, s, len); + b->sz += len; + return 1; + } else { + return 0; + } +} + +int buffer_append_string(buffer *b, const char *s, size_t len) +{ + uint32_t beint = htobe32(len); + if (ensure(b, len + 4)) { + *(uint32_t *)(b->p + b->offs + b->sz) = beint; + memcpy(b->p + b->offs + b->sz + 4, s, len); + b->sz += len + 4; + return 1; + } else { + return 0; + } +} + +int buffer_append_byte(buffer *b, uint8_t x) +{ + if (ensure(b, 1)) { + b->p[b->offs + b->sz] = x; + b->sz += 1; + } else { + return 0; + } +} + +int buffer_append_be16(buffer *b, uint16_t x) +{ + uint16_t beint = htobe16(x); + if (ensure(b, 2)) { + *(uint16_t *)(b->p + b->offs + b->sz) = beint; + b->sz += 2; + } else { + return 0; + } +} + +int buffer_append_be32(buffer *b, uint32_t x) +{ + uint32_t beint = htobe32(x); + if (ensure(b, 4)) { + *(uint32_t *)(b->p + b->offs + b->sz) = beint; + b->sz += 4; + } else { + return 0; + } +} + +void buffer_get(buffer *b, uint8_t *s, size_t len) +{ + memcpy(s, buffer_data(b), len); + buffer_consume(b, len); +} + +uint8_t buffer_get_u8(buffer *b) +{ + uint8_t c = *buffer_data(b); + buffer_consume(b, 1); + return c; +} + +uint16_t buffer_get_u16(buffer *b) +{ + uint16_t u = be16toh(*(uint16_t *)buffer_data(b)); + buffer_consume(b, 2); + return u; +} + +uint32_t buffer_get_u32(buffer *b) +{ + uint32_t u = be32toh(*(uint32_t *)buffer_data(b)); + buffer_consume(b, 4); + return u; +} diff --git a/src/protocol/internal/buffer.h b/src/protocol/internal/buffer.h new file mode 100644 index 0000000..971f21c --- /dev/null +++ b/src/protocol/internal/buffer.h @@ -0,0 +1,65 @@ +/* + * buffer.h: SSH buffer + * Copyright (C) 2018 Iru Cai + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BUFFER_H +#define BUFFER_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* } */ + +typedef struct +{ + uint8_t *p; + size_t alloc; + size_t offs; + size_t sz; +} buffer; + +/* if success, return 1, otherwise return 0 */ +int buffer_init(buffer *); +static inline void buffer_clear(buffer *b) { b->offs = b->sz = 0; } +static inline void buffer_deinit(buffer *b) { free(b->p); } +static inline uint8_t *buffer_data(buffer *b) { return b->p + b->offs; } +static inline size_t buffer_len(buffer *b) { return b->sz; } +int buffer_append(buffer *b, const uint8_t *s, size_t len); +int buffer_append_string(buffer *b, const char *s, size_t len); +int buffer_append_byte(buffer *b, uint8_t); +int buffer_append_be16(buffer *b, uint16_t); +int buffer_append_be32(buffer *b, uint32_t); + +/* the following functions doesn't check on buffer size */ +static inline void buffer_consume(buffer *b, size_t L) +{ + b->offs += L; + b->sz -= L; +} +void buffer_get(buffer *b, uint8_t *s, size_t len); +uint32_t buffer_get_u32(buffer *b); +uint16_t buffer_get_u16(buffer *b); +uint8_t buffer_get_u8(buffer *b); +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3