From b82eadc2e4be1ab43eb802195b91443b2c7a427f Mon Sep 17 00:00:00 2001 From: Aditya <76732801+deadshot8086@users.noreply.github.com> Date: Wed, 17 Jan 2024 12:47:36 +0530 Subject: [PATCH] Add simple POST-command and changed upload path (remote) (#4106) --- .appveyor.yml | 1 + .builds/freebsd.yml | 1 + .builds/netbsd.yml | 1 + .builds/openbsd.yml | 1 + .github/workflows/ci.yml | 6 +- .github/workflows/tcc.yml | 2 +- .travis.yml | 1 + librz/core/rtr_http.c | 524 +++++++++++++++------------ test/db/cmd/cmd_http_post | 10 + test/fuzz/scripts/fuzz_rz_asm.py | 3 +- test/scripts/http_post_cmd_upload.py | 90 +++++ 11 files changed, 411 insertions(+), 229 deletions(-) create mode 100644 test/db/cmd/cmd_http_post create mode 100644 test/scripts/http_post_cmd_upload.py diff --git a/.appveyor.yml b/.appveyor.yml index 4b0833aabc..79a84534f8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -100,6 +100,7 @@ for: - rizin -v - copy C:\Python38-x64\python.exe C:\Python38-x64\python3.exe - python3 -m pip install "git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python" + - python3 -m pip install requests - cd test - git clone -q --depth 1 -c core.symlinks=true https://github.com/rizinorg/rizin-testbins bins - cd .. diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 94d7569e42..6ab714d64f 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -39,6 +39,7 @@ tasks: # Running the unit tests ninja -C build test - test: | + sudo python3 -m ensurepip cd rizin export PATH=${HOME}/bin:${PATH} export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH} diff --git a/.builds/netbsd.yml b/.builds/netbsd.yml index 923754da3f..097bb718f0 100644 --- a/.builds/netbsd.yml +++ b/.builds/netbsd.yml @@ -42,6 +42,7 @@ tasks: # Running the unit tests MALLOC_OPTIONS=S ninja -C build test - test: | + python3.8 -m pip install --user requests cd rizin export PATH=${HOME}/bin:/usr/local/bin:${PATH} export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH} diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml index 4f66af823d..ba646438f7 100644 --- a/.builds/openbsd.yml +++ b/.builds/openbsd.yml @@ -37,6 +37,7 @@ tasks: # Running the unit tests MALLOC_OPTIONS=CFGU ninja -C build test - test: | + /usr/local/bin/python3 -m pip install --user requests cd rizin export PATH=${HOME}/bin:/usr/local/bin:${PATH} export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d388b83c95..e3ec446747 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -195,7 +195,7 @@ jobs: path: test/rz-pipe - name: Install test dependencies if: matrix.run_tests && matrix.enabled - run: pip3 install --user "file://$GITHUB_WORKSPACE/test/rz-pipe#egg=rzpipe&subdirectory=python" + run: pip3 install --user "file://$GITHUB_WORKSPACE/test/rz-pipe#egg=rzpipe&subdirectory=python" requests - name: Install Linux test dependencies if: matrix.run_tests && matrix.enabled && matrix.os != 'macos-12' run: | @@ -427,7 +427,7 @@ jobs: env: PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig - name: Install test dependencies - run: python3 -m pip install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' + run: python3 -m pip install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' requests - name: Run tests # Debug tests fail on old Debian because of the runtime differences, ignore them run: | @@ -450,7 +450,7 @@ jobs: run: sudo pip3 install meson ninja PyYAML - name: Install test dependencies run: | - sudo pip3 install 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' + sudo pip3 install 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' requests sudo apt-get install --yes tzdata debuginfod - name: Checkout rizin run: | diff --git a/.github/workflows/tcc.yml b/.github/workflows/tcc.yml index f49692750c..2b23db911e 100644 --- a/.github/workflows/tcc.yml +++ b/.github/workflows/tcc.yml @@ -90,7 +90,7 @@ jobs: - name: Install test dependencies run: | - python3 -m pip install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' + python3 -m pip install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' requests sudo apt-get update sudo apt-get --assume-yes install libc6 libc6-i386 debuginfod diff --git a/.travis.yml b/.travis.yml index 636b152230..1a6f217620 100644 --- a/.travis.yml +++ b/.travis.yml @@ -50,4 +50,5 @@ script: - | pip3 install -U --user meson ninja pip3 install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python' + pip3 install --user requests $SHELL travis-script diff --git a/librz/core/rtr_http.c b/librz/core/rtr_http.c index ea87a8975e..a5e3083c41 100644 --- a/librz/core/rtr_http.c +++ b/librz/core/rtr_http.c @@ -2,6 +2,300 @@ // SPDX-License-Identifier: LGPL-3.0-only // included from rtr.c +typedef int (*rz_core_rtr_http_handler_ptr)(RzCore *, RzSocketHTTPRequest *, char *); +typedef rz_core_rtr_http_handler_ptr (*rz_core_rtr_http_handler)(); +static int LOOP_CONTINUE_VALUE = 66; + +static int rz_core_rtr_http_cmd(RzCore *core, RzSocketHTTPRequest *rs, char *cmd, char *out, char *headers) { + if ((!strcmp(cmd, "Rh*") || + !strcmp(cmd, "Rh--"))) { + out = NULL; + } else if (*cmd == ':') { + /* commands in /cmd/: starting with : do not show any output */ + rz_core_cmd0(core, cmd + 1); + out = NULL; + } else { + out = rz_core_cmd_str_pipe(core, cmd); + } + + if (out) { + char *res = rz_str_uri_encode(out); + char *newheaders = rz_str_newf( + "Content-Type: text/plain\n%s", headers); + rz_socket_http_response(rs, 200, out, 0, newheaders); + free(out); + free(newheaders); + free(res); + } else { + rz_socket_http_response(rs, 200, "", 0, headers); + } + return 0; +} + +static int rz_core_rtr_http_handler_ok(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + rz_socket_http_response(rs, 200, "", 0, headers); + return 1; +} + +static int rz_core_rtr_http_handler_invalid(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + rz_socket_http_response(rs, 404, "Invalid protocol", 0, headers); + return 1; +} + +static int rz_core_rtr_http_handler_get_file(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + char *dir = NULL; + if (rz_config_get_i(core->config, "http.dirlist")) { + if (rz_file_is_directory(rs->path)) { + dir = strdup(rs->path); + } + } + if (rz_config_get_i(core->config, "http.upget")) { + const char *uproot = rz_config_get(core->config, "http.uproot"); + if (!rs->path[3] || (rs->path[3] == '/' && !rs->path[4])) { + char *ptr = rtr_dir_files(uproot); + rz_socket_http_response(rs, 200, ptr, 0, headers); + free(ptr); + } else { + char *path = rz_file_root(uproot, rs->path + 4); + if (rz_file_exists(path)) { + size_t sz = 0; + char *f = rz_file_slurp(path, &sz); + if (f) { + rz_socket_http_response(rs, 200, f, (int)sz, headers); + free(f); + } else { + rz_socket_http_response(rs, 403, "Permission denied", 0, headers); + http_logf(core, "http: Cannot open '%s'\n", path); + } + } else { + if (dir) { + char *resp = rtr_dir_files(dir); + rz_socket_http_response(rs, 404, resp, 0, headers); + free(resp); + } else { + http_logf(core, "File '%s' not found\n", path); + rz_socket_http_response(rs, 404, "File not found\n", 0, headers); + } + } + free(path); + free(dir); + } + } else { + rz_socket_http_response(rs, 403, "", 0, NULL); + } + return 1; +} + +static int rz_core_rtr_http_handler_get_cmd(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + const bool colon = rz_config_get_i(core->config, "http.colon"); + const char *port = rz_config_get(core->config, "http.port"); + if (colon && rs->path[5] != ':') { + rz_socket_http_response(rs, 403, "Permission denied", 0, headers); + } else { + char *cmd = rs->path + 5; + const char *httpcmd = rz_config_get(core->config, "http.uri"); + const char *httpref = rz_config_get(core->config, "http.referer"); + const bool httpref_enabled = (httpref && *httpref); + char *refstr = NULL; + if (httpref_enabled) { + if (strstr(httpref, "http")) { + refstr = strdup(httpref); + } else { + refstr = rz_str_newf("http://localhost:%d/", atoi(port)); + } + } + + while (*cmd == '/') { + cmd++; + } + if (httpref_enabled && (!rs->referer || (refstr && !strstr(rs->referer, refstr)))) { + rz_socket_http_response(rs, 503, "", 0, headers); + } else { + if (httpcmd && *httpcmd) { + int len; // do remote http query and proxy response + char *res, *bar = rz_str_newf("%s/%s", httpcmd, cmd); + void *bed = rz_cons_sleep_begin(); + res = rz_socket_http_get(bar, NULL, &len); + rz_cons_sleep_end(bed); + if (res) { + res[len] = 0; + rz_cons_println(res); + } + free(bar); + } else { + char *out = NULL, *cmd = rs->path + 5; + rz_str_uri_decode(cmd); + rz_config_set(core->config, "scr.interactive", "false"); + + rz_core_rtr_http_cmd(core, rs, cmd, out, headers); + + if (!strcmp(cmd, "Rh*")) { + rz_socket_http_close(rs); + free(refstr); + return -2; + } else if (!strcmp(cmd, "Rh--")) { + rz_socket_http_close(rs); + free(refstr); + return 0; + } + } + } + free(refstr); + } + return 1; +} + +static int rz_core_rtr_http_handler_get_index(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + char *dir = NULL; + const char *index = rz_config_get(core->config, "http.index"); + if (rz_config_get_i(core->config, "http.dirlist")) { + if (rz_file_is_directory(rs->path)) { + dir = strdup(rs->path); + } + } + const char *root = rz_config_get(core->config, "http.root"); + const char *homeroot = rz_config_get(core->config, "http.homeroot"); + char *path = NULL; + if (!strcmp(rs->path, "/")) { + free(rs->path); + if (*index == '/') { + rs->path = strdup(index); + path = strdup(index); + } else { + rs->path = rz_str_newf("/%s", index); + path = rz_file_root(root, rs->path); + } + } else if (homeroot && *homeroot) { + char *homepath = rz_file_abspath(homeroot); + path = rz_file_root(homepath, rs->path); + free(homepath); + if (!rz_file_exists(path) && !rz_file_is_directory(path)) { + free(path); + path = rz_file_root(root, rs->path); + } + } else { + if (*index == '/') { + path = strdup(index); + } else { + } + } + // FD IS OK HERE + if (rs->path[strlen(rs->path) - 1] == '/') { + path = (*index == '/') ? strdup(index) : rz_str_append(path, index); + } else { + if (rz_file_is_directory(path)) { + char *res = rz_str_newf("Location: %s/\n%s", rs->path, headers); + rz_socket_http_response(rs, 302, NULL, 0, res); + rz_socket_http_close(rs); + free(path); + free(res); + RZ_FREE(dir); + return LOOP_CONTINUE_VALUE; + } + } + if (rz_file_exists(path)) { + size_t sz = 0; + char *f = rz_file_slurp(path, &sz); + if (f) { + const char *ct = NULL; + if (strstr(path, ".js")) { + ct = "Content-Type: application/javascript\n"; + } + if (strstr(path, ".css")) { + ct = "Content-Type: text/css\n"; + } + if (strstr(path, ".html")) { + ct = "Content-Type: text/html\n"; + } + char *hdr = rz_str_newf("%s%s", ct, headers); + rz_socket_http_response(rs, 200, f, (int)sz, hdr); + free(hdr); + free(f); + } else { + rz_socket_http_response(rs, 403, "Permission denied", 0, headers); + http_logf(core, "http: Cannot open '%s'\n", path); + } + } else { + if (dir) { + char *resp = rtr_dir_files(dir); + http_logf(core, "Dirlisting %s\n", dir); + rz_socket_http_response(rs, 404, resp, 0, headers); + free(resp); + } else { + http_logf(core, "File '%s' not found\n", path); + rz_socket_http_response(rs, 404, "File not found\n", 0, headers); + } + } + free(path); + return 1; +} + +static int rz_core_rtr_http_handler_post_upload(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + ut8 *ret; + int retlen; + char buf[128]; + if (rz_config_get_i(core->config, "http.upload")) { + ret = rz_socket_http_handle_upload(rs->data, rs->data_length, &retlen); + if (ret) { + ut64 size = rz_config_get_i(core->config, "http.maxsize"); + if (size && retlen > size) { + rz_socket_http_response(rs, 403, "403 File too big\n", 0, headers); + } else { + char *filename = rz_file_root( + rz_config_get(core->config, "http.uproot"), + rs->path + 8); + http_logf(core, "UPLOADED '%s'\n", filename); + rz_file_dump(filename, ret, retlen, 0); + free(filename); + snprintf(buf, sizeof(buf), + "

uploaded %d byte(s). Thanks

\n", retlen); + rz_socket_http_response(rs, 200, buf, 0, headers); + } + free(ret); + } + + } else { + rz_socket_http_response(rs, 403, "403 Forbidden\n", 0, headers); + } + return 1; +} + +static int rz_core_rtr_http_handler_post_cmd(RzCore *core, RzSocketHTTPRequest *rs, char *headers) { + char *out = NULL; + rz_config_set(core->config, "scr.interactive", "false"); + rz_core_rtr_http_cmd(core, rs, (char *)rs->data, out, headers); + if (!strcmp((char *)rs->data, "Rh*")) { + rz_socket_http_close(rs); + return -2; + } else if (!strcmp((char *)rs->data, "Rh--")) { + rz_socket_http_close(rs); + return 0; + } + return 1; +} + +static rz_core_rtr_http_handler_ptr rz_core_rtr_http_router(RzSocketHTTPRequest *rs) { + if (!strcmp(rs->method, "OPTIONS")) { + return &rz_core_rtr_http_handler_ok; + } else if (!strcmp(rs->method, "GET")) { + if (!strncmp(rs->path, "/up/", strlen("/up/"))) { + return rz_core_rtr_http_handler_get_file; + } else if (!strncmp(rs->path, "/cmd/", strlen("/cmd/"))) { + return rz_core_rtr_http_handler_get_cmd; + } else { + return rz_core_rtr_http_handler_get_index; + } + } else if (!strcmp(rs->method, "POST")) { + if (!strncmp(rs->path, "/upload/", strlen("/upload/"))) { + return rz_core_rtr_http_handler_post_upload; + } else if (!strncmp(rs->path, "/cmd/", strlen("/cmd/"))) { + return rz_core_rtr_http_handler_post_cmd; + } + } + + return rz_core_rtr_http_handler_invalid; +} + static bool is_localhost(const char *address) { if (RZ_STR_ISEMPTY(address)) { return false; @@ -43,7 +337,6 @@ static int rz_core_rtr_http_run(RzCore *core, int launch, int browse, const char char *dir; int iport; const char *bind = rz_config_get(core->config, "http.bind"); - const char *index = rz_config_get(core->config, "http.index"); const char *root = rz_config_get(core->config, "http.root"); const char *homeroot = rz_config_get(core->config, "http.homeroot"); const char *port = rz_config_get(core->config, "http.port"); @@ -235,230 +528,15 @@ static int rz_core_rtr_http_run(RzCore *core, int launch, int browse, const char "Access-Control-Allow-Headers: Origin, " "X-Requested-With, Content-Type, Accept\n"); } - if (!strcmp(rs->method, "OPTIONS")) { - rz_socket_http_response(rs, 200, "", 0, headers); - } else if (!strcmp(rs->method, "GET")) { - if (!strncmp(rs->path, "/up/", 4)) { - if (rz_config_get_i(core->config, "http.upget")) { - const char *uproot = rz_config_get(core->config, "http.uproot"); - if (!rs->path[3] || (rs->path[3] == '/' && !rs->path[4])) { - char *ptr = rtr_dir_files(uproot); - rz_socket_http_response(rs, 200, ptr, 0, headers); - free(ptr); - } else { - char *path = rz_file_root(uproot, rs->path + 4); - if (rz_file_exists(path)) { - size_t sz = 0; - char *f = rz_file_slurp(path, &sz); - if (f) { - rz_socket_http_response(rs, 200, f, (int)sz, headers); - free(f); - } else { - rz_socket_http_response(rs, 403, "Permission denied", 0, headers); - http_logf(core, "http: Cannot open '%s'\n", path); - } - } else { - if (dir) { - char *resp = rtr_dir_files(dir); - rz_socket_http_response(rs, 404, resp, 0, headers); - free(resp); - } else { - http_logf(core, "File '%s' not found\n", path); - rz_socket_http_response(rs, 404, "File not found\n", 0, headers); - } - } - free(path); - } - } else { - rz_socket_http_response(rs, 403, "", 0, NULL); - } - } else if (!strncmp(rs->path, "/cmd/", 5)) { - const bool colon = rz_config_get_i(core->config, "http.colon"); - if (colon && rs->path[5] != ':') { - rz_socket_http_response(rs, 403, "Permission denied", 0, headers); - } else { - char *cmd = rs->path + 5; - const char *httpcmd = rz_config_get(core->config, "http.uri"); - const char *httpref = rz_config_get(core->config, "http.referer"); - const bool httpref_enabled = (httpref && *httpref); - char *refstr = NULL; - if (httpref_enabled) { - if (strstr(httpref, "http")) { - refstr = strdup(httpref); - } else { - refstr = rz_str_newf("http://localhost:%d/", atoi(port)); - } - } - while (*cmd == '/') { - cmd++; - } - if (httpref_enabled && (!rs->referer || (refstr && !strstr(rs->referer, refstr)))) { - rz_socket_http_response(rs, 503, "", 0, headers); - } else { - if (httpcmd && *httpcmd) { - int len; // do remote http query and proxy response - char *res, *bar = rz_str_newf("%s/%s", httpcmd, cmd); - bed = rz_cons_sleep_begin(); - res = rz_socket_http_get(bar, NULL, &len); - rz_cons_sleep_end(bed); - if (res) { - res[len] = 0; - rz_cons_println(res); - } - free(bar); - } else { - char *out, *cmd = rs->path + 5; - rz_str_uri_decode(cmd); - rz_config_set(core->config, "scr.interactive", "false"); - - if ((!strcmp(cmd, "Rh*") || - !strcmp(cmd, "Rh--"))) { - out = NULL; - } else if (*cmd == ':') { - /* commands in /cmd/: starting with : do not show any output */ - rz_core_cmd0(core, cmd + 1); - out = NULL; - } else { - out = rz_core_cmd_str_pipe(core, cmd); - } - - if (out) { - char *res = rz_str_uri_encode(out); - char *newheaders = rz_str_newf( - "Content-Type: text/plain; charset=utf-8\n%s", headers); - rz_socket_http_response(rs, 200, out, 0, newheaders); - free(out); - free(newheaders); - free(res); - } else { - rz_socket_http_response(rs, 200, "", 0, headers); - } - - if (!strcmp(cmd, "Rh*")) { - /* do stuff */ - rz_socket_http_close(rs); - free(dir); - free(refstr); - ret = -2; - goto the_end; - } else if (!strcmp(cmd, "Rh--")) { - rz_socket_http_close(rs); - free(dir); - free(refstr); - ret = 0; - goto the_end; - } - } - } - free(refstr); - } - } else { - const char *root = rz_config_get(core->config, "http.root"); - const char *homeroot = rz_config_get(core->config, "http.homeroot"); - char *path = NULL; - if (!strcmp(rs->path, "/")) { - free(rs->path); - if (*index == '/') { - rs->path = strdup(index); - path = strdup(index); - } else { - rs->path = rz_str_newf("/%s", index); - path = rz_file_root(root, rs->path); - } - } else if (homeroot && *homeroot) { - char *homepath = rz_file_abspath(homeroot); - path = rz_file_root(homepath, rs->path); - free(homepath); - if (!rz_file_exists(path) && !rz_file_is_directory(path)) { - free(path); - path = rz_file_root(root, rs->path); - } - } else { - if (*index == '/') { - path = strdup(index); - } else { - } - } - // FD IS OK HERE - if (rs->path[strlen(rs->path) - 1] == '/') { - path = (*index == '/') ? strdup(index) : rz_str_append(path, index); - } else { - // snprintf (path, sizeof (path), "%s/%s", root, rs->path); - if (rz_file_is_directory(path)) { - char *res = rz_str_newf("Location: %s/\n%s", rs->path, headers); - rz_socket_http_response(rs, 302, NULL, 0, res); - rz_socket_http_close(rs); - free(path); - free(res); - RZ_FREE(dir); - continue; - } - } - if (rz_file_exists(path)) { - size_t sz = 0; - char *f = rz_file_slurp(path, &sz); - if (f) { - const char *ct = NULL; - if (strstr(path, ".js")) { - ct = "Content-Type: application/javascript; charset=utf-8\n"; - } - if (strstr(path, ".css")) { - ct = "Content-Type: text/css; charset=utf-8\n"; - } - if (strstr(path, ".html")) { - ct = "Content-Type: text/html; charset=utf-8\n"; - } - char *hdr = rz_str_newf("%s%s", ct, headers); - rz_socket_http_response(rs, 200, f, (int)sz, hdr); - free(hdr); - free(f); - } else { - rz_socket_http_response(rs, 403, "Permission denied", 0, headers); - http_logf(core, "http: Cannot open '%s'\n", path); - } - } else { - if (dir) { - char *resp = rtr_dir_files(dir); - http_logf(core, "Dirlisting %s\n", dir); - rz_socket_http_response(rs, 404, resp, 0, headers); - free(resp); - } else { - http_logf(core, "File '%s' not found\n", path); - rz_socket_http_response(rs, 404, "File not found\n", 0, headers); - } - } - free(path); - } - } else if (!strcmp(rs->method, "POST")) { - ut8 *ret; - int retlen; - char buf[128]; - if (rz_config_get_i(core->config, "http.upload")) { - ret = rz_socket_http_handle_upload(rs->data, rs->data_length, &retlen); - if (ret) { - ut64 size = rz_config_get_i(core->config, "http.maxsize"); - if (size && retlen > size) { - rz_socket_http_response(rs, 403, "403 File too big\n", 0, headers); - } else { - char *filename = rz_file_root( - rz_config_get(core->config, "http.uproot"), - rs->path + 4); - http_logf(core, "UPLOADED '%s'\n", filename); - rz_file_dump(filename, ret, retlen, 0); - free(filename); - snprintf(buf, sizeof(buf), - "

uploaded %d byte(s). Thanks

\n", retlen); - rz_socket_http_response(rs, 200, buf, 0, headers); - } - free(ret); - } - } else { - rz_socket_http_response(rs, 403, "403 Forbidden\n", 0, headers); - } - } else { - rz_socket_http_response(rs, 404, "Invalid protocol", 0, headers); + int response_result = (*rz_core_rtr_http_router(rs))(core, rs, headers); + if (response_result == 0 || response_result == -2) { + ret = response_result; + goto the_end; + } else if (response_result == LOOP_CONTINUE_VALUE) { + continue; } + rz_socket_http_close(rs); free(dir); } diff --git a/test/db/cmd/cmd_http_post b/test/db/cmd/cmd_http_post new file mode 100644 index 0000000000..c890107cce --- /dev/null +++ b/test/db/cmd/cmd_http_post @@ -0,0 +1,10 @@ +NAME=http-post-cmd +FILE== +CMDS=< +# SPDX-License-Identifier: LGPL-3.0-only + +r""" +This script launches rizin in a subprocess, then uploads a file via new upload path +the it analyzes it with new and old-style http cmd and checks results. +usage: + python3 http_post_cmd_upload.py +""" + +import hashlib +import os +import subprocess +import tempfile +import time + +import requests + +PORT = 28080 +URL = f"http://localhost:{PORT}" +TMP_DIR = tempfile.gettempdir() +TARGET = "./bins/elf/bomb" +SAVED_NAME = "rz_http_test" + + +def start_rizin(cmd): + """Starts rizin""" + return subprocess.Popen(cmd, stderr=subprocess.PIPE, universal_newlines=True) + + +def main(): + """Main function""" + popen = start_rizin( + [ + "rizin", + "-q", + f"-e http.port={PORT}", + "-e http.upload=1", + f"-e http.root={TMP_DIR}", + f"-e http.uproot={TMP_DIR}", + "-cRh", + ] + ) + time.sleep(5) + + # upload the binary via new /upload path + boundary = b"------------------------f8a8a5c708553bc9" + head = b'\r\nContent-Disposition: form-data; name="upload"; filename="upload"\r\n\ + Content-Type: application/octet-stream\r\n\r\n' + + md5 = hashlib.md5() + + with open(TARGET, "rb") as file: + file_content = file.read() + + md5.update(file_content) + + data = boundary + head + file_content + b"\r\n" + boundary + requests.post( + URL + "/upload/" + SAVED_NAME, + data=data, + headers={"Content-Type": f"multipart/form-data; boundary={str(boundary)}"}, + timeout=5, + ) + + cmd = f"!rz-hash -a md5 {TMP_DIR}/{SAVED_NAME}" + + # analyze the file via new POST-cmd + post_cmd = requests.post(URL + "/cmd/", data=cmd, timeout=5) + post_text = post_cmd.text.split("md5: ")[1].rstrip() + + # analyze the file by old GET-cmd + get_cmd = requests.get(URL + "/cmd/" + cmd, timeout=5) + get_text = get_cmd.text.split("md5: ")[1].rstrip() + + # compare results + if post_text == get_text: + print("New and old cmd results equal") + # compare md5 + if md5.hexdigest() == post_text: + print("Test succeeded") + + os.remove(TMP_DIR + "/" + SAVED_NAME) + popen.kill() + + +if __name__ == "__main__": + main()