mirror of
https://github.com/aydencharles/onionHEN.git
synced 2026-10-22 11:53:07 -05:00
296 lines
11 KiB
C
296 lines
11 KiB
C
/* Host unit tests for libonion_payload payload helpers (no elfldr socket). */
|
|
#include "test_harness.h"
|
|
#include "test_support.h"
|
|
|
|
#include <onion/payload.h>
|
|
#include <onion/elf_name.h>
|
|
#include <elfldr_remote.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
void onion_test_elfldr_reset(void);
|
|
void onion_test_elfldr_configure(bool available, pid_t launch_pid);
|
|
int onion_test_elfldr_launch_calls(void);
|
|
uint16_t onion_test_elfldr_last_port(void);
|
|
const char *onion_test_elfldr_last_path(void);
|
|
void onion_test_live_pid(pid_t pid);
|
|
|
|
static int test_is_elf(void) {
|
|
const unsigned char elf[8] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0};
|
|
const unsigned char junk[4] = {0, 0, 0, 0};
|
|
|
|
TEST_ASSERT_TRUE(onion_payload_is_elf(elf, sizeof(elf)));
|
|
TEST_ASSERT_TRUE(!onion_payload_is_elf(junk, sizeof(junk)));
|
|
TEST_ASSERT_TRUE(!onion_payload_is_elf(elf, 3));
|
|
TEST_ASSERT_TRUE(!onion_payload_is_elf(NULL, 16));
|
|
return 0;
|
|
}
|
|
|
|
static int test_pid_path(void) {
|
|
char path[128];
|
|
onion_payload_pid_path(path, sizeof(path), "mytool");
|
|
TEST_ASSERT_STREQ("/tmp/onionhen/pid/mytool.PID", path);
|
|
return 0;
|
|
}
|
|
|
|
static int test_elf_name_stem(void) {
|
|
TEST_ASSERT_EQ_INT(3, (int)onion_elf_name_stem_n("foo.elf", 7));
|
|
TEST_ASSERT_EQ_INT(3, (int)onion_elf_name_stem_n("foo", 3));
|
|
TEST_ASSERT_EQ_INT(0, (int)onion_elf_name_stem_n(".elf", 4));
|
|
TEST_ASSERT_TRUE(onion_elf_name_has_suffix("foo.elf", 7));
|
|
TEST_ASSERT_TRUE(!onion_elf_name_has_suffix("foo", 3));
|
|
TEST_ASSERT_TRUE(!onion_elf_name_has_suffix(".elf.bak", 8));
|
|
return 0;
|
|
}
|
|
|
|
static int test_elf_key_from_name(void) {
|
|
char key[64];
|
|
TEST_ASSERT_TRUE(onion_payload_elf_key_from_name("foo.elf", key, sizeof(key)));
|
|
TEST_ASSERT_STREQ("foo", key);
|
|
TEST_ASSERT_TRUE(
|
|
onion_payload_elf_key_from_name("/data/OnionHEN/payloads/bar.elf", key,
|
|
sizeof(key)));
|
|
TEST_ASSERT_STREQ("bar", key);
|
|
TEST_ASSERT_TRUE(onion_payload_elf_key_from_name("noext", key, sizeof(key)));
|
|
TEST_ASSERT_STREQ("noext", key);
|
|
TEST_ASSERT_TRUE(!onion_payload_elf_key_from_name(".elf", key, sizeof(key)));
|
|
TEST_ASSERT_TRUE(!onion_payload_elf_key_from_name(NULL, key, sizeof(key)));
|
|
TEST_ASSERT_TRUE(!onion_payload_elf_key_from_name("", key, sizeof(key)));
|
|
return 0;
|
|
}
|
|
|
|
static int test_path_identity(void) {
|
|
char first[ONION_PAYLOAD_IDENTITY_SIZE];
|
|
char repeated[ONION_PAYLOAD_IDENTITY_SIZE];
|
|
char second[ONION_PAYLOAD_IDENTITY_SIZE];
|
|
|
|
TEST_ASSERT_TRUE(onion_payload_identity_from_path(
|
|
"/data/OnionHEN/payloads/tool.elf", first, sizeof(first)));
|
|
TEST_ASSERT_TRUE(onion_payload_identity_from_path(
|
|
"/data/OnionHEN/payloads/tool.elf", repeated, sizeof(repeated)));
|
|
TEST_ASSERT_TRUE(onion_payload_identity_from_path(
|
|
"/mnt/usb0/OnionHEN/payloads/tool.elf", second, sizeof(second)));
|
|
TEST_ASSERT_STREQ(first, repeated);
|
|
TEST_ASSERT_TRUE(strcmp(first, second) != 0);
|
|
TEST_ASSERT_EQ_INT(17, (int)strlen(first));
|
|
TEST_ASSERT_TRUE(first[0] == 'p');
|
|
TEST_ASSERT_TRUE(!onion_payload_identity_from_path("", first, sizeof(first)));
|
|
TEST_ASSERT_TRUE(!onion_payload_identity_from_path(
|
|
"/data/OnionHEN/payloads/tool.elf", first, sizeof(first) - 1));
|
|
return 0;
|
|
}
|
|
|
|
static int test_pid_file_roundtrip(void) {
|
|
char path[256];
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(".PID", "", 0, path,
|
|
sizeof(path)));
|
|
|
|
onion_payload_write_pid_file(path, 4242);
|
|
TEST_ASSERT_EQ_INT(4242, (int)onion_payload_read_pid_file(path));
|
|
|
|
onion_payload_write_pid_file(path, -1);
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_read_pid_file(path));
|
|
|
|
onion_payload_write_pid_file(path, 1);
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_read_pid_file(path));
|
|
onion_payload_write_pid_file(path, 0);
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_read_pid_file(path));
|
|
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_read_pid_file(
|
|
"/tmp/onion-payload-pid-missing-xyz.PID"));
|
|
onion_test_remove_file(path);
|
|
return 0;
|
|
}
|
|
|
|
static int test_read_file(void) {
|
|
char path[256];
|
|
const char payload[] = "hello-payload";
|
|
size_t sz = 0;
|
|
uint8_t *buf = NULL;
|
|
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(".bin", payload,
|
|
sizeof(payload) - 1, path,
|
|
sizeof(path)));
|
|
buf = onion_payload_read_file(path, &sz);
|
|
TEST_ASSERT_TRUE(buf != NULL);
|
|
TEST_ASSERT_EQ_U64(sizeof(payload) - 1, sz);
|
|
TEST_ASSERT_MEMEQ(payload, buf, sizeof(payload) - 1);
|
|
free(buf);
|
|
|
|
TEST_ASSERT_TRUE(onion_payload_read_file(NULL, &sz) == NULL);
|
|
TEST_ASSERT_TRUE(onion_payload_read_file(path, NULL) == NULL);
|
|
TEST_ASSERT_TRUE(onion_payload_read_file("/tmp/onion-missing-payload-xyz",
|
|
&sz) == NULL);
|
|
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(".bin", "", 0, path,
|
|
sizeof(path)));
|
|
TEST_ASSERT_TRUE(onion_payload_read_file(path, &sz) == NULL);
|
|
onion_test_remove_file(path);
|
|
return 0;
|
|
}
|
|
|
|
static int test_strict_private_loader_policy(void) {
|
|
const char *path = "/data/OnionHEN/payloads/strict-test.elf";
|
|
|
|
onion_test_elfldr_reset();
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_launch_elfldr(
|
|
"strict-test", path));
|
|
TEST_ASSERT_EQ_INT(0, onion_test_elfldr_launch_calls());
|
|
|
|
onion_test_elfldr_configure(true, 4242);
|
|
TEST_ASSERT_EQ_INT(4242, (int)onion_payload_launch_elfldr(
|
|
"strict-test", path));
|
|
TEST_ASSERT_EQ_INT(1, onion_test_elfldr_launch_calls());
|
|
TEST_ASSERT_EQ_INT(ONION_ELFLDR_PORT, onion_test_elfldr_last_port());
|
|
TEST_ASSERT_STREQ(path, onion_test_elfldr_last_path());
|
|
|
|
onion_test_elfldr_configure(true, 0);
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_launch_elfldr(
|
|
"strict-test", path));
|
|
TEST_ASSERT_EQ_INT(2, onion_test_elfldr_launch_calls());
|
|
|
|
onion_test_elfldr_configure(true, -1);
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_launch_elfldr(
|
|
"strict-test", path));
|
|
TEST_ASSERT_EQ_INT(3, onion_test_elfldr_launch_calls());
|
|
return 0;
|
|
}
|
|
|
|
static int test_load_requires_real_pid(void) {
|
|
char path[256];
|
|
char pid_path[256];
|
|
const unsigned char elf[8] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0};
|
|
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(
|
|
".elf", elf, sizeof(elf), path, sizeof(path)));
|
|
|
|
onion_test_elfldr_reset();
|
|
onion_test_elfldr_configure(true, 5151);
|
|
TEST_ASSERT_TRUE(onion_payload_load(path, NULL));
|
|
TEST_ASSERT_STREQ(path, onion_test_elfldr_last_path());
|
|
|
|
char path_copy[256];
|
|
snprintf(path_copy, sizeof(path_copy), "%s", path);
|
|
const char *base = strrchr(path_copy, '/');
|
|
base = base ? base + 1 : path_copy;
|
|
char key[64];
|
|
TEST_ASSERT_TRUE(onion_payload_elf_key_from_name(base, key, sizeof(key)));
|
|
onion_payload_pid_path(pid_path, sizeof(pid_path), key);
|
|
TEST_ASSERT_EQ_INT(5151, (int)onion_payload_read_pid_file(pid_path));
|
|
|
|
onion_test_elfldr_configure(true, 0);
|
|
TEST_ASSERT_TRUE(!onion_payload_load(path, NULL));
|
|
TEST_ASSERT_EQ_INT(-1, (int)onion_payload_read_pid_file(pid_path));
|
|
|
|
onion_test_remove_file(path);
|
|
onion_test_remove_file(pid_path);
|
|
return 0;
|
|
}
|
|
|
|
static int test_payload_running_without_live_pid(void) {
|
|
TEST_ASSERT_TRUE(!onion_payload_running(NULL));
|
|
TEST_ASSERT_TRUE(!onion_payload_running("missing-title"));
|
|
return 0;
|
|
}
|
|
|
|
static int test_load_preserves_running_instance(void) {
|
|
char path[256];
|
|
char pid_path[256];
|
|
char key[64];
|
|
const unsigned char elf[8] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0};
|
|
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(
|
|
".elf", elf, sizeof(elf), path, sizeof(path)));
|
|
const char *base = strrchr(path, '/');
|
|
base = base ? base + 1 : path;
|
|
TEST_ASSERT_TRUE(onion_payload_elf_key_from_name(base, key, sizeof(key)));
|
|
onion_payload_pid_path(pid_path, sizeof(pid_path), key);
|
|
onion_payload_write_pid_file(pid_path, 6262);
|
|
|
|
onion_test_elfldr_reset();
|
|
onion_test_live_pid(6262);
|
|
onion_test_elfldr_configure(true, 7373);
|
|
TEST_ASSERT_TRUE(onion_payload_load(path, NULL));
|
|
TEST_ASSERT_EQ_INT(0, onion_test_elfldr_launch_calls());
|
|
TEST_ASSERT_EQ_INT(6262, (int)onion_payload_read_pid_file(pid_path));
|
|
|
|
onion_test_elfldr_reset();
|
|
onion_test_remove_file(pid_path);
|
|
onion_test_remove_file(path);
|
|
return 0;
|
|
}
|
|
|
|
static int test_load_with_explicit_key(void) {
|
|
char path[256];
|
|
char pid_path[256];
|
|
const char key[] = "p0123456789abcdef";
|
|
const unsigned char elf[8] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0};
|
|
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(
|
|
".elf", elf, sizeof(elf), path, sizeof(path)));
|
|
onion_test_elfldr_reset();
|
|
onion_test_elfldr_configure(true, 8181);
|
|
TEST_ASSERT_TRUE(onion_payload_load_with_key(path, NULL, key));
|
|
onion_payload_pid_path(pid_path, sizeof(pid_path), key);
|
|
TEST_ASSERT_EQ_INT(8181, (int)onion_payload_read_pid_file(pid_path));
|
|
|
|
onion_test_remove_file(pid_path);
|
|
onion_test_remove_file(path);
|
|
return 0;
|
|
}
|
|
|
|
static int test_builtin_identity_payloads_allowed(void) {
|
|
char path[256];
|
|
const unsigned char elf[8] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0};
|
|
|
|
TEST_ASSERT_EQ_INT(0, onion_test_write_temp_file(
|
|
".elf", elf, sizeof(elf), path, sizeof(path)));
|
|
|
|
onion_test_elfldr_reset();
|
|
onion_test_elfldr_configure(true, 5151);
|
|
TEST_ASSERT_EQ_INT(5151, (int)onion_payload_launch_elfldr(
|
|
"ftpsrv", path));
|
|
TEST_ASSERT_TRUE(onion_payload_load(path, "ftpsrv.elf"));
|
|
TEST_ASSERT_TRUE(onion_payload_load(path, "ftpsrv-ps5.elf"));
|
|
TEST_ASSERT_TRUE(onion_payload_load(path, "kstuff.elf"));
|
|
TEST_ASSERT_EQ_INT(4, onion_test_elfldr_launch_calls());
|
|
|
|
char pid_path[256];
|
|
onion_payload_pid_path(pid_path, sizeof(pid_path), "ftpsrv");
|
|
onion_test_remove_file(pid_path);
|
|
onion_payload_pid_path(pid_path, sizeof(pid_path), "ftpsrv-ps5");
|
|
onion_test_remove_file(pid_path);
|
|
onion_payload_pid_path(pid_path, sizeof(pid_path), "kstuff");
|
|
onion_test_remove_file(pid_path);
|
|
onion_test_remove_file(path);
|
|
return 0;
|
|
}
|
|
|
|
int test_payload_suite(void) {
|
|
int failures = 0;
|
|
failures += onion_test_run("payload.is_elf", test_is_elf);
|
|
failures += onion_test_run("payload.pid_path", test_pid_path);
|
|
failures += onion_test_run("payload.elf_name_stem", test_elf_name_stem);
|
|
failures += onion_test_run("payload.elf_key_from_name", test_elf_key_from_name);
|
|
failures += onion_test_run("payload.path_identity", test_path_identity);
|
|
failures += onion_test_run("payload.pid_file_roundtrip",
|
|
test_pid_file_roundtrip);
|
|
failures += onion_test_run("payload.read_file", test_read_file);
|
|
failures += onion_test_run("payload.strict_private_loader_policy",
|
|
test_strict_private_loader_policy);
|
|
failures += onion_test_run("payload.load_requires_real_pid",
|
|
test_load_requires_real_pid);
|
|
failures += onion_test_run("payload.running_without_live_pid",
|
|
test_payload_running_without_live_pid);
|
|
failures += onion_test_run("payload.load_preserves_running_instance",
|
|
test_load_preserves_running_instance);
|
|
failures += onion_test_run("payload.load_with_explicit_key",
|
|
test_load_with_explicit_key);
|
|
failures += onion_test_run("payload.builtin_identity_payloads_allowed",
|
|
test_builtin_identity_payloads_allowed);
|
|
return failures;
|
|
}
|