Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/dependencies.lock
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ manifest = "build/legacy-manifest.json"
schema = 1
component_count = 331
file_count = 1972
byte_count = 260959742
byte_count = 260958446
source_build_components = 232
unresolved_components = 99
inherited_baseline = "07505ea58c7bba698d6b9220ff43946a43cac76b"
Expand Down
4 changes: 2 additions & 2 deletions build/legacy-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2321,8 +2321,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/script/network",
"file_count": 5,
"byte_count": 23560,
"tree_sha256": "c0c20b192a1f736c4e8d6ff20dd0ffbf8133d20e98e12229dd1cacae022fd593",
"byte_count": 22264,
"tree_sha256": "5ba1040d9523790b3d6c57ac31bf9cf3819eef365567f9af2f4057daf96d4562",
"source": "https://github.com/OnionUI/Onion",
"source_revision": "07505ea58c7bba698d6b9220ff43946a43cac76b",
"license": "GPL-3.0-only",
Expand Down
4 changes: 2 additions & 2 deletions docs/1.0_TEST_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ shoulder button.
| Critical lifecycle | Exact 640x480 and 752x560 built-in projections; source/target/path and legacy-file rejection; boot/shutdown/save/low-battery/recovery/Safe Mode ignore theme/config/media; charging reflects bounded actual level; installer uses one deterministic surface; missing optional text/font fallback; signed Full-update boot/charging/shutdown/recovery checkpoint |
| Settings | One sectioned surface; inline values; capability filtering; one-layer details; hidden Developer section; optional overlapping L1/R1 list paging |
| Quick Settings | START from core surfaces; immediate brightness/volume/mute; capability-gated Wi-Fi opens the dedicated detail surface; Wi-Fi left/right never mutates the radio; readable battery; B/START close |
| Network services | Desired/runtime separation; carrier without IPv4 remains acquiring/not-ready; canonical DHCP restart and bounded post-address listener reconciliation; SSH shell and SFTP independent key-only states; canonical transfer roots and modes; Saves read-only; private roots denied; traversal/symlink/path bounds; same-filesystem atomic publication; authorized-key import; quiesce/health; stale FTP/Telnet/FileBrowser/inherited-Samba/WPS/hotspot flags cannot activate listeners; process-aware listener audit; inherited FTP/Telnet/FileBrowser HTTP launcher and Tweaks exposure plus rejected Samba payloads absent from newly assembled stable artifacts while older-card remnants remain locked down |
| Network services | Desired/runtime separation; carrier without IPv4 remains acquiring/not-ready; canonical DHCP restart and bounded post-address listener reconciliation; SSH shell and SFTP independent key-only states; canonical transfer roots and modes; Saves read-only; private roots denied; traversal/symlink/path bounds; same-filesystem atomic publication; authorized-key import; quiesce/health; stale FTP/Telnet/FileBrowser/inherited-Samba/WPS/hotspot flags cannot activate listeners; process-aware listener audit; inherited FTP/Telnet/FileBrowser HTTP and rejected Samba launchers, configurations, and Tweaks exposure absent from newly assembled stable artifacts while older-card remnants remain locked down |
| Wi-Fi profile store | JFFS2 private root; stdin-only bounded replacement and `bloomctl network profile upsert ID`; requested/document ID binding; explicit `network forget ID`; inactive-ID deletion with active-profile refusal; active forget only after a separately confirmed fallback connection; schema/unknown-field/count/size enforcement; WPA2-PSK, explicit open, and manual hidden WPA2; WEP and hidden open denial; unique IDs/SSIDs; redacted status; explicit local credential-free UI list with one active marker; sanitized `network connect status` with internal profile-handle validation and public omission; mode-0600 atomic single-profile supplicant projection; symlink, occupied-slot, live-lock, invalid-profile, and prior-byte preservation |
| Wi-Fi scan API | Asynchronous start; redacted status; explicit ID-scoped local results; cancel and terminal discard; one active worker; five-second rate limit; 15-second runtime; 64-KiB raw ceiling; 32 unique printable SSIDs; eight-operation history; open/WPA2-PSK/unsupported classification; duplicate signal reconciliation; backend failure, timeout, oversize, unsafe-path, stale/live-lock, and unsupported-hardware handling |
| Wi-Fi UI | Original Mini hidden; Settings, Shell Quick Settings, and GameSwitcher Quick Settings converge on `--settings-wifi`; direct radio toggle removed; bounded fixed-argv profile-list load outside render; connection state and saved-network detail; selectable Scan/Cancel row and read-only discovered networks; active-only 100-ms SDL wake; deferred GameSwitcher until cancellation discard; single-flight nonblocking fixed-argv scan client; 16-KiB output and five-second deadline; child process-group cleanup; controller-owned start/status/results/discard and cancel-during-start sequencing; 250-ms status opportunities; exact profile/scan/ack schemas; 16 profiles and 32 networks; unique bounded IDs/SSIDs; one active profile; fixed scan phases/errors; terminal history discarded; open/WPA2 profile form with shared keyboard, masked secret, fixed profile-upsert argv, escaped stdin JSON, strict ID/SSID/PSK validation, explicit secret clearing, nonblocking submit/poll, 4-KiB acknowledgement cap, exact upsert response, timeout process-group cleanup, exact saved-ID reuse, 104-bit no-follow random new handles, collision/security/full-store rejection, one editing/submitting controller with 100-ms poll opportunities, exact cancellation, terminal clearing, bounded focus return, supported scan-result selection, explicit saved-not-connected result, and no implicit association; explicit inactive-profile X/confirm forget flow; active-row refusal in Shell and store; fixed nonblocking delete; exact acknowledgement; terminal projection reload; graceful TERM cleanup before bounded KILL; exact guarded-connect status model with fixed phases/operations/failures, lease consistency, 64-byte transaction-ID and 300-second deadline ceilings, and discarded transaction/overlay identity; fixed no-follow `network connect status` loader with less-than-4-KiB output, five-second read ceiling, and stale-state clearing; separately typed single-flight nonblocking status request with process-group timeout and generic-poller refusal; controller-owned single request, 100-ms opportunities, duplicate-begin refusal, typed terminal state, teardown reaping, explicit guarded-state presentation, one-second freshness, fail-closed mutation gating for stale/unavailable/lease-armed/rollback-failed results, read-only refresh without queued intent, and exit teardown; credential and unknown-field rejection; passwords absent from arguments, logs, screenshots, durable Shell state, and evidence |
Expand Down Expand Up @@ -91,7 +91,7 @@ shoulder button.
| System View recognition, Continue, populated systems, and empty-system hiding | not-run | blocked-physical | not-run | not-run |
| Game-list discovery, exact restoration, and held-scroll control | not-run | blocked-physical | not-run | not-run |
| Flat Settings, footer density, and focus visibility | not-run | blocked-physical | not-run | not-run |
| Optional L1/R1 list paging and SSH/SFTP/Samba controls | not-run | partial-remote | not-run | not-run |
| Optional L1/R1 list paging and SSH/SFTP controls | not-run | partial-remote | not-run | not-run |
| MENU GameSwitcher and START Quick Settings consistency | not-run | blocked-physical | not-run | not-run |

The signed Plus UX-convergence evidence is recorded in
Expand Down
5 changes: 5 additions & 0 deletions docs/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ The inherited bftpd executables, anonymous/authenticated configurations, start
logic, default credentials, and visible Tweaks controls are excluded as well;
stale FTP state cleanup and exact `bftpd` termination remain for older-card
compatibility.
The rejected inherited Samba executable and libraries remain excluded, and its
configuration, dormant start logic, share editor, default credentials, and
visible Tweaks controls are no longer shipped or exposed. The signed disable
migration, stale-state cleanup, and exact `smbd` termination remain for
older-card compatibility.
The reviewed key-only Dropbear transport is the only stable remote listener;
SFTP is independently gated and confined through that same transport.
Its chroot is materialized from the versioned canonical transfer policy rather
Expand Down
2 changes: 0 additions & 2 deletions src/tweaks/appstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,13 @@ bool isMenu(List *target)
static List _menu_network;
static List _menu_wifi;
static List _menu_wps;
static List _menu_smbd;
static List _menu_vnc;

void menu_network_free_all(void)
{
list_free(&_menu_network);
list_free(&_menu_wifi);
list_free(&_menu_wps);
list_free(&_menu_smbd);
list_free(&_menu_vnc);
}

Expand Down
200 changes: 1 addition & 199 deletions src/tweaks/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@
#include "./appstate.h"

#define NET_SCRIPT_PATH "/mnt/SDCARD/.tmp_update/script/network"
#define SMBD_CONFIG_PATH "/mnt/SDCARD/.tmp_update/config/smb.conf"

static struct network_s {
bool smbd;
bool hotspot;
bool ntp;
bool ntp_wait;
bool auth_smbd;
bool manual_tz;
bool check_updates;
bool keep_alive;
Expand All @@ -48,7 +45,6 @@ void network_loadState(void)
if (network_state.loaded)
return;

network_state.smbd = config_flag_get(".smbdState");
network_state.hotspot = config_flag_get(".hotspotState");
network_state.ntp = config_flag_get(".ntpState");
network_state.ntp_wait = config_flag_get(".ntpWait");
Expand All @@ -61,131 +57,6 @@ void network_loadState(void)
network_state.loaded = true;
}

typedef struct {
char name[STR_MAX - 11];
char path[STR_MAX];
int available; // 1 if available = yes, 0 otherwise
long availablePos; // in file position for the available property
} Share;

static Share *_network_shares = NULL;
static int network_numShares;

void network_freeSmbShares()
{
if (_network_shares != NULL) {
free(_network_shares);
}
}

void network_getSmbShares()
{
if (_network_shares != NULL) {
return;
}

int numShares = 0;

FILE *file = fopen(SMBD_CONFIG_PATH, "r");
if (file == NULL) {
printf("Failed to open smb.conf file.\n");
return;
}

char line[STR_MAX];

bool found_shares = false;
bool is_available = false;
long availablePos = -1;

while (fgets(line, sizeof(line), file) != NULL) {
char *trimmedLine = strtok(line, "\n");
if (trimmedLine == NULL) {
continue;
}

if (strstr(trimmedLine, "available = ") != NULL) {
availablePos = ftell(file) - strlen(trimmedLine) - 1;
is_available = strstr(trimmedLine, "1") != NULL;
continue;
}

if (strstr(trimmedLine, "path = ") != NULL) {
strncpy(_network_shares[numShares - 1].path, trimmedLine + 7, STR_MAX);
continue;
}

if (strncmp(trimmedLine, "[", 1) == 0 && strncmp(trimmedLine + strlen(trimmedLine) - 1, "]", 1) == 0) {
if (found_shares) {
_network_shares[numShares - 1].available = is_available;
_network_shares[numShares - 1].availablePos = availablePos;
is_available = false;
}

char *shareName = strtok(trimmedLine + 1, "]");
if (shareName != NULL && strlen(shareName) > 0) {
if (strcmp(shareName, "global") == 0) {
continue;
}

numShares++;
_network_shares = (Share *)realloc(_network_shares, numShares * sizeof(Share));

bool add_exclamation = false;
if (strncmp("__", shareName, 2) == 0) {
shareName = shareName + 2;
add_exclamation = true;
}

strncpy(_network_shares[numShares - 1].name, shareName, STR_MAX - 11);

if (add_exclamation) {
strncat(_network_shares[numShares - 1].name, " (!)", STR_MAX - 11 - strlen(shareName));
}

found_shares = true;
}
}
}

if (found_shares) {
_network_shares[numShares - 1].available = is_available;
_network_shares[numShares - 1].availablePos = availablePos;
}

network_numShares = numShares;

fclose(file);
}

void network_toggleSmbAvailable(void *item)
{
ListItem *listItem = (ListItem *)item;
Share *share = (Share *)listItem->payload_ptr;

FILE *file = fopen(SMBD_CONFIG_PATH, "r+");
if (file == NULL) {
printf("Failed to open smb.conf file.\n");
return;
}

if (fseek(file, share->availablePos, SEEK_SET) != 0) {
printf("Failed to seek to the available property of share '%s'.\n", share->name);
fclose(file);
return;
}

char line[STR_MAX];
fgets(line, sizeof(line), file);
share->available = strstr(line, "1") == NULL; // toggle

fseek(file, share->availablePos, SEEK_SET);
fprintf(file, "available = %d\n", share->available);
fflush(file);

fclose(file);
}

void network_setState(bool *state_ptr, const char *flag_name, bool value)
{
*state_ptr = value;
Expand All @@ -208,23 +79,6 @@ void network_execServiceState(const char *service_name, bool background)
printf_debug("network_execServiceState: %s\n", state);
}

void network_commonEnableToggle(List *list, ListItem *item, bool *value_pt, const char *service_name, const char *service_flag)
{
bool enabled = item->value == 1;
network_setState(value_pt, service_flag, enabled);
if (_menu_network._created) {
list_currentItem(&_menu_network)->value = enabled;
}
network_execServiceState(service_name, false);
reset_menus = true;
all_changed = true;
}

void network_setSmbdState(void *pt)
{
network_commonEnableToggle(&_menu_smbd, (ListItem *)pt, &network_state.smbd, "smbd", ".smbdState");
}

void network_setHotspotState(void *pt)
{
network_setState(&network_state.hotspot, ".hotspotState", ((ListItem *)pt)->value);
Expand Down Expand Up @@ -349,43 +203,6 @@ void network_setVNCFPS(void *pt)
}
}

void menu_smbd(void *pt)
{
ListItem *item = (ListItem *)pt;
item->value = (int)network_state.smbd;

if (!_menu_smbd._created) {
network_getSmbShares();

_menu_smbd = list_createWithSticky(1 + network_numShares, "Samba");

list_addItemWithInfoNote(&_menu_smbd,
(ListItem){
.label = "Enable",
.sticky_note = "Enable Samba file sharing",
.item_type = TOGGLE,
.value = (int)network_state.smbd,
.action = network_setSmbdState},
item->info_note);

for (int i = 0; i < network_numShares; i++) {
ListItem shareItem = {
.item_type = TOGGLE,
.disabled = !network_state.smbd,
.action = network_toggleSmbAvailable, // set the action to the wrapper function
.value = _network_shares[i].available,
.payload_ptr = _network_shares + i // store a pointer to the share in the payload
};
snprintf(shareItem.label, STR_MAX - 1, "Share: %s", _network_shares[i].name);
strncpy(shareItem.sticky_note, str_replace(_network_shares[i].path, "/mnt/SDCARD", "SD:"), STR_MAX - 1);
list_addItem(&_menu_smbd, shareItem);
}
}

menu_stack[++menu_level] = &_menu_smbd;
header_changed = true;
}

void menu_wps(void *_)
{
if (!_menu_wps._created) {
Expand Down Expand Up @@ -472,7 +289,7 @@ void menu_wifi(void *_)
void menu_network(void *_)
{
if (!_menu_network._created) {
_menu_network = list_create(7, LIST_SMALL);
_menu_network = list_create(6, LIST_SMALL);
strcpy(_menu_network.title, "Network");

network_loadState();
Expand All @@ -486,21 +303,6 @@ void menu_network(void *_)
(ListItem){
.label = "WiFi: Hotspot/WPS...",
.action = menu_wifi});
list_addItemWithInfoNote(&_menu_network,
(ListItem){
.label = "Samba: Network file share...",
.item_type = TOGGLE,
.disabled = !settings.wifi_on,
.alternative_arrow_action = true,
.arrow_action = network_setSmbdState,
.value = (int)network_state.smbd,
.action = menu_smbd},
"Samba is a file sharing protocol that provides\n"
"integrated sharing of files and directories\n"
"between your Miyoo Mini Plus and your PC.\n"
" \n"
"Username: onion\n"
"Password: onion\n");
list_addItemWithInfoNote(&_menu_network,
(ListItem){
.label = "VNC: Screen share...",
Expand Down
1 change: 0 additions & 1 deletion src/tweaks/tweaks.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ int main(int argc, char *argv[])

Mix_CloseAudio();

network_freeSmbShares();
diags_freeEntries();

display_close();
Expand Down
50 changes: 2 additions & 48 deletions static/build/.tmp_update/script/network/update_networking.sh
Original file line number Diff line number Diff line change
Expand Up @@ -200,49 +200,6 @@ wifi_off() {
/customer/app/axp_test wifioff
}

# Starts the samba daemon if the toggle is set to on
check_smbdstate() {
if flag_enabled smbdState; then
if is_running smbd; then
if wifi_disabled; then
log "Samba: Wifi is turned off, disabling the toggle for smbd and killing the process"
disable_flag smbdState
killall -9 smbd
fi
else
if wifi_enabled; then
sync

mkdir -p \
/var/lib/samba \
/var/run/samba/ncalrpc \
/var/private \
/var/log/

$netscript/start_smbd.sh $PASS &
log "Samba: Starting smbd.."
else
disable_flag smbdState
fi
fi
else
if is_running smbd; then
killall -9 smbd
log "Samba: Killed"
fi
fi
}

smbd_authed() {
if flag_enabled smbdState; then
update_smbconf
if is_running smbd; then
killall -9 smbd
fi
$netscript/start_smbd.sh $PASS &
fi
}

# Starts only Bloom's explicit developer-mode, key-only SSH service.
check_sshstate() {
if $sysdir/bin/bloom-dev-ssh start; then
Expand Down Expand Up @@ -392,12 +349,9 @@ set_tzid() {
}

print_usage() {
echo "Usage: $0 {check|ftp|telnet|http|smbd|disableall|save|restore|full_reset} [toggle|authed]"
echo " - For {ftp|telnet|http|ssh|smbd}, [toggle|authed] can be specified."
echo " - Commands {ntp|hotspot} only accept 'toggle'."
echo "Usage: $0 {check|services|ntp|disableall|save|restore|full_reset} [toggle]"
echo " - Command {ntp} only accepts 'toggle'."
echo " - Commands {save|restore|full_reset} do not require additional args."
echo "e.g:"
echo "ftp toggle - Will toggle the current FTP state"
exit 1
}

Expand Down
Loading
Loading