Add simple POST-command and changed upload path (remote) (#4106)
This commit is contained in:
parent
df93e2c003
commit
b82eadc2e4
11 changed files with 411 additions and 229 deletions
|
|
@ -100,6 +100,7 @@ for:
|
||||||
- rizin -v
|
- rizin -v
|
||||||
- copy C:\Python38-x64\python.exe C:\Python38-x64\python3.exe
|
- 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 "git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python"
|
||||||
|
- python3 -m pip install requests
|
||||||
- cd test
|
- cd test
|
||||||
- git clone -q --depth 1 -c core.symlinks=true https://github.com/rizinorg/rizin-testbins bins
|
- git clone -q --depth 1 -c core.symlinks=true https://github.com/rizinorg/rizin-testbins bins
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ tasks:
|
||||||
# Running the unit tests
|
# Running the unit tests
|
||||||
ninja -C build test
|
ninja -C build test
|
||||||
- test: |
|
- test: |
|
||||||
|
sudo python3 -m ensurepip
|
||||||
cd rizin
|
cd rizin
|
||||||
export PATH=${HOME}/bin:${PATH}
|
export PATH=${HOME}/bin:${PATH}
|
||||||
export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH}
|
export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ tasks:
|
||||||
# Running the unit tests
|
# Running the unit tests
|
||||||
MALLOC_OPTIONS=S ninja -C build test
|
MALLOC_OPTIONS=S ninja -C build test
|
||||||
- test: |
|
- test: |
|
||||||
|
python3.8 -m pip install --user requests
|
||||||
cd rizin
|
cd rizin
|
||||||
export PATH=${HOME}/bin:/usr/local/bin:${PATH}
|
export PATH=${HOME}/bin:/usr/local/bin:${PATH}
|
||||||
export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH}
|
export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ tasks:
|
||||||
# Running the unit tests
|
# Running the unit tests
|
||||||
MALLOC_OPTIONS=CFGU ninja -C build test
|
MALLOC_OPTIONS=CFGU ninja -C build test
|
||||||
- test: |
|
- test: |
|
||||||
|
/usr/local/bin/python3 -m pip install --user requests
|
||||||
cd rizin
|
cd rizin
|
||||||
export PATH=${HOME}/bin:/usr/local/bin:${PATH}
|
export PATH=${HOME}/bin:/usr/local/bin:${PATH}
|
||||||
export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH}
|
export LD_LIBRARY_PATH=${HOME}/lib:${HOME}/lib64:${LD_LIBRARY_PATH}
|
||||||
|
|
|
||||||
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
|
@ -195,7 +195,7 @@ jobs:
|
||||||
path: test/rz-pipe
|
path: test/rz-pipe
|
||||||
- name: Install test dependencies
|
- name: Install test dependencies
|
||||||
if: matrix.run_tests && matrix.enabled
|
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
|
- name: Install Linux test dependencies
|
||||||
if: matrix.run_tests && matrix.enabled && matrix.os != 'macos-12'
|
if: matrix.run_tests && matrix.enabled && matrix.os != 'macos-12'
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -427,7 +427,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig
|
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig
|
||||||
- name: Install test dependencies
|
- 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
|
- name: Run tests
|
||||||
# Debug tests fail on old Debian because of the runtime differences, ignore them
|
# Debug tests fail on old Debian because of the runtime differences, ignore them
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -450,7 +450,7 @@ jobs:
|
||||||
run: sudo pip3 install meson ninja PyYAML
|
run: sudo pip3 install meson ninja PyYAML
|
||||||
- name: Install test dependencies
|
- name: Install test dependencies
|
||||||
run: |
|
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
|
sudo apt-get install --yes tzdata debuginfod
|
||||||
- name: Checkout rizin
|
- name: Checkout rizin
|
||||||
run: |
|
run: |
|
||||||
|
|
|
||||||
2
.github/workflows/tcc.yml
vendored
2
.github/workflows/tcc.yml
vendored
|
|
@ -90,7 +90,7 @@ jobs:
|
||||||
|
|
||||||
- name: Install test dependencies
|
- name: Install test dependencies
|
||||||
run: |
|
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 update
|
||||||
sudo apt-get --assume-yes install libc6 libc6-i386 debuginfod
|
sudo apt-get --assume-yes install libc6 libc6-i386 debuginfod
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,4 +50,5 @@ script:
|
||||||
- |
|
- |
|
||||||
pip3 install -U --user meson ninja
|
pip3 install -U --user meson ninja
|
||||||
pip3 install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python'
|
pip3 install --user 'git+https://github.com/rizinorg/rz-pipe#egg=rzpipe&subdirectory=python'
|
||||||
|
pip3 install --user requests
|
||||||
$SHELL travis-script
|
$SHELL travis-script
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,300 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-only
|
// SPDX-License-Identifier: LGPL-3.0-only
|
||||||
// included from rtr.c
|
// 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),
|
||||||
|
"<html><body><h2>uploaded %d byte(s). Thanks</h2>\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) {
|
static bool is_localhost(const char *address) {
|
||||||
if (RZ_STR_ISEMPTY(address)) {
|
if (RZ_STR_ISEMPTY(address)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -43,7 +337,6 @@ static int rz_core_rtr_http_run(RzCore *core, int launch, int browse, const char
|
||||||
char *dir;
|
char *dir;
|
||||||
int iport;
|
int iport;
|
||||||
const char *bind = rz_config_get(core->config, "http.bind");
|
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 *root = rz_config_get(core->config, "http.root");
|
||||||
const char *homeroot = rz_config_get(core->config, "http.homeroot");
|
const char *homeroot = rz_config_get(core->config, "http.homeroot");
|
||||||
const char *port = rz_config_get(core->config, "http.port");
|
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, "
|
"Access-Control-Allow-Headers: Origin, "
|
||||||
"X-Requested-With, Content-Type, Accept\n");
|
"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 == '/') {
|
int response_result = (*rz_core_rtr_http_router(rs))(core, rs, headers);
|
||||||
cmd++;
|
if (response_result == 0 || response_result == -2) {
|
||||||
}
|
ret = response_result;
|
||||||
if (httpref_enabled && (!rs->referer || (refstr && !strstr(rs->referer, refstr)))) {
|
goto the_end;
|
||||||
rz_socket_http_response(rs, 503, "", 0, headers);
|
} else if (response_result == LOOP_CONTINUE_VALUE) {
|
||||||
} else {
|
continue;
|
||||||
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),
|
|
||||||
"<html><body><h2>uploaded %d byte(s). Thanks</h2>\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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rz_socket_http_close(rs);
|
rz_socket_http_close(rs);
|
||||||
free(dir);
|
free(dir);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
test/db/cmd/cmd_http_post
Normal file
10
test/db/cmd/cmd_http_post
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
NAME=http-post-cmd
|
||||||
|
FILE==
|
||||||
|
CMDS=<<EOF
|
||||||
|
!python3 scripts/http_post_cmd_upload.py
|
||||||
|
EOF
|
||||||
|
REGEXP_FILTER_OUT=(Test succ.+)
|
||||||
|
EXPECT=<<EOF
|
||||||
|
Test succeeded
|
||||||
|
EOF
|
||||||
|
RUN
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from concurrent.futures import ProcessPoolExecutor
|
from concurrent.futures import ProcessPoolExecutor
|
||||||
|
|
||||||
|
|
@ -178,6 +179,4 @@ def main():
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
|
||||||
|
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|
|
||||||
90
test/scripts/http_post_cmd_upload.py
Normal file
90
test/scripts/http_post_cmd_upload.py
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2024 RizinOrg <info@rizin.re>
|
||||||
|
# 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()
|
||||||
Loading…
Reference in a new issue