diff --git a/build/dependencies.lock b/build/dependencies.lock
index 8962c619..f30737e8 100644
--- a/build/dependencies.lock
+++ b/build/dependencies.lock
@@ -207,11 +207,11 @@ legacy_channels = ["development"]
[legacy_inventory]
manifest = "build/legacy-manifest.json"
schema = 1
-component_count = 333
-file_count = 1974
-byte_count = 261292177
+component_count = 331
+file_count = 1972
+byte_count = 260959742
source_build_components = 232
-unresolved_components = 101
+unresolved_components = 99
inherited_baseline = "07505ea58c7bba698d6b9220ff43946a43cac76b"
[themes]
diff --git a/build/legacy-manifest.json b/build/legacy-manifest.json
index 536baaf3..30f2c6ae 100644
--- a/build/legacy-manifest.json
+++ b/build/legacy-manifest.json
@@ -431,32 +431,6 @@
"build_recipe": null,
"resolution": "replace-source-build-or-exclude"
},
- {
- "id": "runtime-tmp-update-bin-bftpd",
- "kind": "runtime",
- "path": "static/build/.tmp_update/bin/bftpd",
- "file_count": 1,
- "byte_count": 268895,
- "tree_sha256": "2ac00ecd46d5af4fafd125dce4fb753c804fe63d400b0946dbee32b64950c566",
- "source": null,
- "source_revision": null,
- "license": null,
- "build_recipe": null,
- "resolution": "replace-source-build-or-exclude"
- },
- {
- "id": "runtime-tmp-update-bin-bftpdutmp",
- "kind": "runtime",
- "path": "static/build/.tmp_update/bin/bftpdutmp",
- "file_count": 1,
- "byte_count": 62100,
- "tree_sha256": "7ac25e26813dbf435940025f1432d2ebcf04856ad5f1ac5d81a5de0370a8060d",
- "source": null,
- "source_revision": null,
- "license": null,
- "build_recipe": null,
- "resolution": "replace-source-build-or-exclude"
- },
{
"id": "runtime-tmp-update-bin-bloom-controls",
"kind": "runtime",
@@ -2347,8 +2321,8 @@
"kind": "runtime",
"path": "static/build/.tmp_update/script/network",
"file_count": 5,
- "byte_count": 25000,
- "tree_sha256": "0a925e68531db9099042ecf3ffbb3af5249cc5ae3ed2001c1468ca4eb9b99e0e",
+ "byte_count": 23560,
+ "tree_sha256": "c0c20b192a1f736c4e8d6ff20dd0ffbf8133d20e98e12229dd1cacae022fd593",
"source": "https://github.com/OnionUI/Onion",
"source_revision": "07505ea58c7bba698d6b9220ff43946a43cac76b",
"license": "GPL-3.0-only",
diff --git a/docs/1.0_TEST_MATRIX.md b/docs/1.0_TEST_MATRIX.md
index 87eae64c..d1de1482 100644
--- a/docs/1.0_TEST_MATRIX.md
+++ b/docs/1.0_TEST_MATRIX.md
@@ -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; dormant Telnet and FileBrowser HTTP launcher/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 launcher and Tweaks exposure plus rejected Samba payloads 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 |
diff --git a/docs/SECURITY.md b/docs/SECURITY.md
index 49224a1b..a2ee3326 100644
--- a/docs/SECURITY.md
+++ b/docs/SECURITY.md
@@ -26,6 +26,10 @@ are no longer exposed by the stable UI.
The inherited Telnet environment launcher, dormant start logic, and visible
Tweaks toggle are also excluded; stale-state cleanup and exact BusyBox
`telnetd` termination remain for older-card compatibility.
+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 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
diff --git a/src/tweaks/appstate.h b/src/tweaks/appstate.h
index 7d2f361c..34ff8550 100644
--- a/src/tweaks/appstate.h
+++ b/src/tweaks/appstate.h
@@ -17,7 +17,6 @@ bool isMenu(List *target)
static List _menu_network;
static List _menu_wifi;
-static List _menu_ftp;
static List _menu_wps;
static List _menu_smbd;
static List _menu_vnc;
@@ -26,7 +25,6 @@ void menu_network_free_all(void)
{
list_free(&_menu_network);
list_free(&_menu_wifi);
- list_free(&_menu_ftp);
list_free(&_menu_wps);
list_free(&_menu_smbd);
list_free(&_menu_vnc);
diff --git a/src/tweaks/network.h b/src/tweaks/network.h
index 2c311baf..75ddc6e1 100644
--- a/src/tweaks/network.h
+++ b/src/tweaks/network.h
@@ -28,12 +28,10 @@
static struct network_s {
bool smbd;
- bool ftp;
bool hotspot;
bool ntp;
bool ntp_wait;
bool auth_smbd;
- bool auth_ftp;
bool manual_tz;
bool check_updates;
bool keep_alive;
@@ -51,12 +49,10 @@ void network_loadState(void)
return;
network_state.smbd = config_flag_get(".smbdState");
- network_state.ftp = config_flag_get(".ftpState");
network_state.hotspot = config_flag_get(".hotspotState");
network_state.ntp = config_flag_get(".ntpState");
network_state.ntp_wait = config_flag_get(".ntpWait");
network_state.force_wifi_on_startup = config_flag_get(".ntpForce");
- network_state.auth_ftp = config_flag_get(".authftpState");
network_state.manual_tz = config_flag_get(".manual_tz");
network_state.check_updates = config_flag_get(".checkUpdates");
network_state.keep_alive = config_flag_get(".keepServicesAlive");
@@ -212,21 +208,6 @@ void network_execServiceState(const char *service_name, bool background)
printf_debug("network_execServiceState: %s\n", state);
}
-void network_execServiceAuth(const char *service_name)
-{
- char authed[256];
- char command[512];
-
- sync();
-
- sprintf(authed, NET_SCRIPT_PATH "/update_networking.sh %s authed", service_name);
- sprintf(command, "%s 2>&1", authed);
-
- system(command);
-
- printf_debug("network_execServiceAuth: %s\n", authed);
-}
-
void network_commonEnableToggle(List *list, ListItem *item, bool *value_pt, const char *service_name, const char *service_flag)
{
bool enabled = item->value == 1;
@@ -244,11 +225,6 @@ void network_setSmbdState(void *pt)
network_commonEnableToggle(&_menu_smbd, (ListItem *)pt, &network_state.smbd, "smbd", ".smbdState");
}
-void network_setFtpState(void *pt)
-{
- network_commonEnableToggle(&_menu_ftp, (ListItem *)pt, &network_state.ftp, "ftp", ".ftpState");
-}
-
void network_setHotspotState(void *pt)
{
network_setState(&network_state.hotspot, ".hotspotState", ((ListItem *)pt)->value);
@@ -286,12 +262,6 @@ void network_keepServicesAlive(void *pt)
network_setState(&network_state.keep_alive, ".keepServicesAlive", !((ListItem *)pt)->value);
}
-void network_setFtpAuthState(void *pt)
-{
- network_setState(&network_state.auth_ftp, ".authftpState", ((ListItem *)pt)->value);
- network_execServiceAuth("ftp");
-}
-
void network_wpsConnect(void *pt)
{
system("sh " NET_SCRIPT_PATH "/wpsclient.sh");
@@ -416,37 +386,6 @@ void menu_smbd(void *pt)
header_changed = true;
}
-void menu_ftp(void *pt)
-{
- ListItem *item = (ListItem *)pt;
- item->value = (int)network_state.ftp;
- if (!_menu_ftp._created) {
- _menu_ftp = list_create(2, LIST_SMALL);
- strcpy(_menu_ftp.title, "FTP");
- list_addItemWithInfoNote(&_menu_ftp,
- (ListItem){
- .label = "Enable",
- .item_type = TOGGLE,
- .value = (int)network_state.ftp,
- .action = network_setFtpState},
- item->info_note);
- list_addItemWithInfoNote(&_menu_ftp,
- (ListItem){
- .label = "Enable authentication",
- .item_type = TOGGLE,
- .disabled = !network_state.ftp,
- .value = (int)network_state.auth_ftp,
- .action = network_setFtpAuthState},
- "Username: onion\n"
- "Password: onion\n"
- " \n"
- "We're using a new auth system. User defined\n"
- "passwords will come in a future update.");
- }
- menu_stack[++menu_level] = &_menu_ftp;
- header_changed = true;
-}
-
void menu_wps(void *_)
{
if (!_menu_wps._created) {
@@ -533,7 +472,7 @@ void menu_wifi(void *_)
void menu_network(void *_)
{
if (!_menu_network._created) {
- _menu_network = list_create(8, LIST_SMALL);
+ _menu_network = list_create(7, LIST_SMALL);
strcpy(_menu_network.title, "Network");
network_loadState();
@@ -562,19 +501,6 @@ void menu_network(void *_)
" \n"
"Username: onion\n"
"Password: onion\n");
- list_addItemWithInfoNote(&_menu_network,
- (ListItem){
- .label = "FTP: File server...",
- .item_type = TOGGLE,
- .disabled = !settings.wifi_on,
- .alternative_arrow_action = true,
- .arrow_action = network_setFtpState,
- .value = (int)network_state.ftp,
- .action = menu_ftp},
- "FTP provides a method of transferring files\n"
- "between BloomOS and a PC, phone, or tablet.\n"
- "You'll need an FTP client installed on the\n"
- "other device.");
list_addItemWithInfoNote(&_menu_network,
(ListItem){
.label = "VNC: Screen share...",
diff --git a/src/tweaks/tweaks.c b/src/tweaks/tweaks.c
index 21c4dbd7..4f6f9172 100644
--- a/src/tweaks/tweaks.c
+++ b/src/tweaks/tweaks.c
@@ -46,7 +46,6 @@ void check_networkChanged(void)
{
bool modified = temp_flag_get("network_changed");
modified |= check_menuHasChanges(&_menu_network);
- modified |= check_menuHasChanges(&_menu_ftp);
modified |= check_menuHasChanges(&_menu_date_time);
temp_flag_set("network_changed", modified);
}
diff --git a/static/build/.tmp_update/bin/bftpd b/static/build/.tmp_update/bin/bftpd
deleted file mode 100644
index adc08c1d..00000000
Binary files a/static/build/.tmp_update/bin/bftpd and /dev/null differ
diff --git a/static/build/.tmp_update/bin/bftpdutmp b/static/build/.tmp_update/bin/bftpdutmp
deleted file mode 100644
index 98048634..00000000
Binary files a/static/build/.tmp_update/bin/bftpdutmp and /dev/null differ
diff --git a/static/build/.tmp_update/script/network/update_networking.sh b/static/build/.tmp_update/script/network/update_networking.sh
index 64705e4a..97eaccda 100644
--- a/static/build/.tmp_update/script/network/update_networking.sh
+++ b/static/build/.tmp_update/script/network/update_networking.sh
@@ -243,51 +243,6 @@ smbd_authed() {
fi
}
-# Starts bftpd if the toggle is set to on
-check_ftpstate() {
- if flag_enabled ftpState; then
- if is_running bftpd; then
- if wifi_disabled; then
- log "FTP: Wifi is turned off, disabling the toggle for FTP and killing the process"
- disable_flag ftpState
- killall -9 bftpd
- fi
- else
- if wifi_enabled; then
- log "FTP: Starting bftpd"
- sync
- if flag_enabled authftpState; then
- ftp_authed
- else
- bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf
- log "FTP: Starting bftpd without auth"
- fi
- else
- disable_flag ftpState
- fi
- fi
- else
- if is_running bftpd; then
- killall -9 bftpd
- log "FTP: Killed"
- fi
- fi
-}
-
-# Called by above function on boot or when auth state is toggled in tweaks
-ftp_authed() {
- if flag_enabled ftpState; then
- if is_running_exact "bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf" || flag_enabled authftpState; then
- killall -9 bftpd
- bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpdauth.conf
- log "FTP: Starting bftpd with auth"
- else
- killall -9 bftpd
- bftpd -d -c /mnt/SDCARD/.tmp_update/config/bftpd.conf
- fi
- fi
-}
-
# Starts only Bloom's explicit developer-mode, key-only SSH service.
check_sshstate() {
if $sysdir/bin/bloom-dev-ssh start; then
diff --git a/static/configs/.tmp_update/config/bftpd.conf b/static/configs/.tmp_update/config/bftpd.conf
deleted file mode 100644
index 3900d7a4..00000000
--- a/static/configs/.tmp_update/config/bftpd.conf
+++ /dev/null
@@ -1,79 +0,0 @@
- global {
- DENY_LOGIN="no"
- PORT="21"
- PASSIVE_PORTS="0"
- DATAPORT20="no"
- ADMIN_PASS="x"
- PATH_BFTPDUTMP="/mnt/SDCARD/.tmp_update/bin/bftpdutmp"
- XFER_BUFSIZE="64000"
- CHANGE_BUFSIZE="yes"
- XFER_DELAY="0"
- SHOW_HIDDEN_FILES="always"
- SHOW_NONREADABLE_FILES="yes"
- ALLOW_FXP="no"
- CONTROL_TIMEOUT="300"
- DATA_TIMEOUT="30"
- RATIO="none"
- ROOTDIR="/mnt/SDCARD"
- UMASK="022"
- LOGFILE="/mnt/SDCARD/.tmp_update/logs/ftp.log"
- HELLO_STRING="Onion ftp at %i ready."
- AUTO_CHDIR="/mnt/SDCARD"
- AUTH="PASSWD"
- RESOLVE_CLIENT_IP="no"
- MOTD_GLOBAL="/mnt/SDCARD/.tmp_update/config/ftpmotd"
- MOTD_USER="/mnt/SDCARD/.tmp_update/config/.ftpmotd"
- RESOLVE_UIDS="yes"
- DO_CHROOT="no"
- LOG_WTMP="no"
- BIND_TO_ADDR="any"
- AUTH_ETCSHELLS="no"
- ALLOWCOMMAND_DELE="yes"
- ALLOWCOMMAND_STOR="yes"
- ALLOWCOMMAND_SITE="yes"
- HIDE_GROUP=""
- QUIT_MSG="See you later, have a good game !"
- USERLIMIT_GLOBAL="0"
- USERLIMIT_SINGLEUSER="0"
- USERLIMIT_HOST="0"
- GZ_UPLOAD="yes"
- GZ_DOWNLOAD="yes"
- }
-
-
-user anonymous {
-
-#If the client wants anonymous, ftp is taken instead.
-ALIAS="ftp"
-}
-
-
-user ftp {
-#Any password fits.
-ANONYMOUS_USER="yes"
-ALLOWCOMMAND_NLST="yes"
-ALLOWCOMMAND_LIST="yes"
-ALLOWCOMMAND_DELE="yes"
-ALLOWCOMMAND_STOR="yes"
-ALLOWCOMMAND_MKD="yes"
-ALLOWCOMMAND_RMD="yes"
-ALLOWCOMMAND_XMKD="yes"
-ALLOWCOMMAND_XRMD="yes"
-SHOW_HIDDEN_FILES="no"
-INITIAL_CHROOT="/mnt/SDCARD/"
-DO_CHROOT="yes"
-}
-
-
-user root {
-DENY_LOGIN="no"
-ALLOWCOMMAND_NLST="yes"
-ALLOWCOMMAND_LIST="yes"
-ALLOWCOMMAND_DELE="yes"
-ALLOWCOMMAND_STOR="yes"
-ALLOWCOMMAND_MKD="yes"
-ALLOWCOMMAND_RMD="yes"
-ALLOWCOMMAND_XMKD="yes"
-ALLOWCOMMAND_XRMD="yes"
-}
-
diff --git a/static/configs/.tmp_update/config/bftpdauth.conf b/static/configs/.tmp_update/config/bftpdauth.conf
deleted file mode 100644
index 6d0f4f0a..00000000
--- a/static/configs/.tmp_update/config/bftpdauth.conf
+++ /dev/null
@@ -1,65 +0,0 @@
- global {
- DENY_LOGIN="no"
- PORT="21"
- PASSIVE_PORTS="0"
- DATAPORT20="no"
- ADMIN_PASS="x"
- PATH_BFTPDUTMP="/mnt/SDCARD/.tmp_update/bin/bftpdutmp"
- XFER_BUFSIZE="64000"
- CHANGE_BUFSIZE="yes"
- XFER_DELAY="0"
- SHOW_HIDDEN_FILES="always"
- SHOW_NONREADABLE_FILES="yes"
- ALLOW_FXP="no"
- CONTROL_TIMEOUT="300"
- DATA_TIMEOUT="30"
- RATIO="none"
- ROOTDIR="/mnt/SDCARD"
- UMASK="022"
- LOGFILE="/mnt/SDCARD/.tmp_update/logs/ftp.log"
- HELLO_STRING="Onion ftp at %i ready."
- AUTO_CHDIR="/mnt/SDCARD"
- AUTH="PASSWD"
- RESOLVE_CLIENT_IP="no"
- MOTD_GLOBAL="/mnt/SDCARD/.tmp_update/config/ftpmotd"
- MOTD_USER="/mnt/SDCARD/.tmp_update/config/.ftpmotd"
- RESOLVE_UIDS="yes"
- DO_CHROOT="no"
- LOG_WTMP="no"
- BIND_TO_ADDR="any"
- AUTH_ETCSHELLS="no"
- ALLOWCOMMAND_DELE="yes"
- ALLOWCOMMAND_STOR="yes"
- ALLOWCOMMAND_SITE="yes"
- HIDE_GROUP=""
- QUIT_MSG="See you later, have a good game!"
- USERLIMIT_GLOBAL="0"
- USERLIMIT_SINGLEUSER="0"
- USERLIMIT_HOST="0"
- GZ_UPLOAD="yes"
- GZ_DOWNLOAD="yes"
- }
-
-
-user anonymous {
-# If the client wants anonymous, ftp is taken instead.
-ALIAS="onion"
-}
-
-user onion {
-DENY_LOGIN="no"
-ALLOWCOMMAND_NLST="yes"
-ALLOWCOMMAND_LIST="yes"
-ALLOWCOMMAND_DELE="yes"
-ALLOWCOMMAND_STOR="yes"
-ALLOWCOMMAND_MKD="yes"
-ALLOWCOMMAND_RMD="yes"
-ALLOWCOMMAND_XMKD="yes"
-ALLOWCOMMAND_XRMD="yes"
-INITIAL_CHROOT="/"
-DO_CHROOT="yes"
-}
-
-user root {
-DENY_LOGIN="yes"
-}
\ No newline at end of file
diff --git a/test/shell/branding_copy.bats b/test/shell/branding_copy.bats
index 70627561..c0c5fda9 100644
--- a/test/shell/branding_copy.bats
+++ b/test/shell/branding_copy.bats
@@ -4,9 +4,9 @@
run python3 /workspace/tools/validate_branding_copy.py --repository /workspace
[ "$status" -eq 0 ]
- [[ "$output" == "branding copy validate: 10 classified legacy literals" ]]
+ [[ "$output" == "branding copy validate: 8 classified legacy literals" ]]
! grep -F 'website hosted by' /workspace/src/tweaks/network.h
- grep -F 'between BloomOS and a PC' /workspace/src/tweaks/network.h
+ ! grep -F 'FTP provides' /workspace/src/tweaks/network.h
grep -F 'Reset all BloomOS system settings' /workspace/src/tweaks/menus.h
grep -F 'BloomOS save folder map' /workspace/static/configs/Saves/CurrentProfile/saves/README.txt
grep -F 'label = BloomOS-v{VERSION}' /workspace/static/build/autorun.inf
diff --git a/test/shell/ci_validation.bats b/test/shell/ci_validation.bats
index 15df9c12..83f61282 100644
--- a/test/shell/ci_validation.bats
+++ b/test/shell/ci_validation.bats
@@ -127,3 +127,19 @@
[ "$status" -eq 0 ]
[ "$output" = "full" ]
}
+
+@test "stable FTP payload removal keeps packaging exhaustive and cppcheck scoped" {
+ scope=/workspace/tools/ci-scope.sh
+ run sh -c "printf '%s\n' static/build/.tmp_update/bin/bftpd | '$scope' build"
+ [ "$status" -eq 0 ]
+ [ "$output" = "full" ]
+ run sh -c "printf '%s\n' static/configs/.tmp_update/config/bftpd.conf | '$scope' static-analysis"
+ [ "$status" -eq 0 ]
+ [ "$output" = "none" ]
+ run sh -c "printf '%s\n' static/build/.tmp_update/bin/bftpdutmp | '$scope' risk"
+ [ "$status" -eq 0 ]
+ [ "$output" = "3" ]
+ run sh -c "printf '%s\n' static/configs/.tmp_update/config/bftpdauth.conf | '$scope' shell-tests"
+ [ "$status" -eq 0 ]
+ [ "$output" = "full" ]
+}
diff --git a/test/shell/legacy_manifest.bats b/test/shell/legacy_manifest.bats
index 128e50cb..67a4bbfd 100644
--- a/test/shell/legacy_manifest.bats
+++ b/test/shell/legacy_manifest.bats
@@ -6,7 +6,7 @@
--manifest /workspace/build/legacy-manifest.json
[ "$status" -eq 0 ]
- [[ "$output" == "legacy manifest validate: 333 components" ]]
+ [[ "$output" == "legacy manifest validate: 331 components" ]]
[ ! -e "/workspace/static/packages/RApp/SNK - Neo Geo (GnGeo)" ]
[ ! -e "/workspace/static/packages/RApp/PICO-8 (PICO-8 standalone)" ]
[ ! -e "/workspace/static/packages/RApp/SCUMM (ScummVM standalone)" ]
@@ -47,6 +47,8 @@ assert "runtime-tmp-update-bin-bloom-samba-service" not in components
assert "runtime-tmp-update-bin-samba" not in components
assert "runtime-tmp-update-lib-samba" not in components
assert "runtime-tmp-update-bin-filebrowser" not in components
+assert "runtime-tmp-update-bin-bftpd" not in components
+assert "runtime-tmp-update-bin-bftpdutmp" not in components
assert components["runtime-tmp-update-bin-bloom-dev-deploy"]["resolution"] == "source-build"
assert components["runtime-tmp-update-bin-bloom-display-session-prepare"]["resolution"] == "source-build"
assert components["runtime-tmp-update-res-bloom"]["resolution"] == "source-build"
diff --git a/test/shell/listener_lockdown.bats b/test/shell/listener_lockdown.bats
index 88d95cf6..51956a9a 100644
--- a/test/shell/listener_lockdown.bats
+++ b/test/shell/listener_lockdown.bats
@@ -111,6 +111,31 @@ EOF
! grep -Fi 'telnet' /workspace/website/docs/07-apps/03-network-features/06-hotspot.md
}
+@test "stable payload exposes no FTP launcher, configuration, or Tweaks toggle" {
+ network=/workspace/static/build/.tmp_update/script/network/update_networking.sh
+ tweaks=/workspace/src/tweaks/network.h
+
+ [ ! -e /workspace/static/build/.tmp_update/bin/bftpd ]
+ [ ! -e /workspace/static/build/.tmp_update/bin/bftpdutmp ]
+ [ ! -e /workspace/static/configs/.tmp_update/config/bftpd.conf ]
+ [ ! -e /workspace/static/configs/.tmp_update/config/bftpdauth.conf ]
+ ! grep -F 'check_ftpstate()' "$network"
+ ! grep -F 'ftp_authed()' "$network"
+ ! grep -F 'bftpd -d' "$network"
+ grep -F 'disable_flag ftpState' "$network"
+ grep -F 'disable_flag authftpState' "$network"
+ grep -F 'for process in bftpd filebrowser telnetd hostapd dnsmasq smbd; do' "$network"
+ ! grep -F 'network_state.ftp' "$tweaks"
+ ! grep -F 'network_setFtpState' "$tweaks"
+ ! grep -F 'FTP: File server' "$tweaks"
+ ftp_doc=/workspace/website/docs/07-apps/03-network-features/04-ftp.md
+ grep -F 'BloomOS does not ship or start the inherited FTP server' "$ftp_doc"
+ grep -F '/docs/network/ssh' "$ftp_doc"
+ ! grep -F 'Enabling FTP access' "$ftp_doc"
+ ! grep -F 'FTP: File server' /workspace/website/docs/07-apps/01-included-in-onion/tweaks.mdx
+ ! grep -F 'FTP on the go' /workspace/website/docs/07-apps/03-network-features/06-hotspot.md
+}
+
@test "stable compatibility reconciliation ignores stale flags and stops inherited processes" {
root="$BATS_TEST_TMPDIR/root"
sysdir="$root/mnt/SDCARD/.tmp_update"
diff --git a/test/test_retroarch_build_identity.py b/test/test_retroarch_build_identity.py
index d3e2dda8..e5355778 100644
--- a/test/test_retroarch_build_identity.py
+++ b/test/test_retroarch_build_identity.py
@@ -36,9 +36,9 @@ def test_identity_is_stable_for_unrelated_inventory_totals(self):
self.assertRegex(baseline.stdout.strip(), r"^[0-9a-f]{64}$")
changed = LOCK.read_text(encoding="utf-8")
- changed = changed.replace("component_count = 333", "component_count = 999")
- changed = changed.replace("file_count = 1974", "file_count = 9999")
- changed = changed.replace("byte_count = 261292177", "byte_count = 999999999")
+ changed = changed.replace("component_count = 331", "component_count = 999")
+ changed = changed.replace("file_count = 1972", "file_count = 9999")
+ changed = changed.replace("byte_count = 260959742", "byte_count = 999999999")
self.assertNotEqual(changed, LOCK.read_text(encoding="utf-8"))
with tempfile.TemporaryDirectory() as directory:
candidate = pathlib.Path(directory) / "dependencies.lock"
diff --git a/tools/ci-scope.sh b/tools/ci-scope.sh
index 41aab80f..efaa5c06 100755
--- a/tools/ci-scope.sh
+++ b/tools/ci-scope.sh
@@ -292,6 +292,12 @@ while IFS= read -r path; do
# stable payload and therefore retains the complete ARM gate.
[ "$mode" != build ] || full=1
;;
+ static/build/.tmp_update/bin/bftpd|static/build/.tmp_update/bin/bftpdutmp|\
+ static/configs/.tmp_update/config/bftpd.conf|static/configs/.tmp_update/config/bftpdauth.conf)
+ # Stable FTP payload deletion requires complete ARM packaging but
+ # does not expand unrelated C/C++ static analysis.
+ [ "$mode" != build ] || full=1
+ ;;
build/dependencies.lock|build/legacy-manifest.json|build/core-selection-policy*.json|\
build/core-inventory-disposition*.json|\
build/save-migration-policy*.json|\
@@ -515,6 +521,14 @@ while IFS= read -r path; do
add_shell_target /workspace/test/shell/provenance_policy.bats
add_shell_target /workspace/test/shell/fat_payload.bats
;;
+ static/build/.tmp_update/bin/bftpd|static/build/.tmp_update/bin/bftpdutmp|\
+ static/configs/.tmp_update/config/bftpd.conf|static/configs/.tmp_update/config/bftpdauth.conf)
+ raise_risk 3
+ add_shell_target /workspace/test/shell/listener_lockdown.bats
+ add_shell_target /workspace/test/shell/legacy_manifest.bats
+ add_shell_target /workspace/test/shell/provenance_policy.bats
+ add_shell_target /workspace/test/shell/fat_payload.bats
+ ;;
test/test_bloom_ui_system_view.cpp|src/bloomUi/bloom_ui_system_view.c|src/bloomUi/bloom_ui_system_view.h)
raise_risk 1
add_native_filter 'BloomUiSystemView*'
diff --git a/website/docs/01-features/index.md b/website/docs/01-features/index.md
index 94864258..24dd5087 100644
--- a/website/docs/01-features/index.md
+++ b/website/docs/01-features/index.md
@@ -210,7 +210,7 @@ For the Miyoo Mini Plus (equipped with wifi) Onion offers many additional possib
- [Automatic date/time synchronisation](apps/tweaks#set-automatically-via-the-internet) (NTP, via Tweaks app)
- [Retroachivements](https://www.retroarch.com/?page=achievements)
- [Scraper](/docs/apps/scraper): import game covers directly from your MMP
-- [Network Services](network-features): [Samba/SMB share](network/samba), [HTTP server (retired)](network/http), [SSH](network/ssh), [FTP](network/ftp), [Hotspot](network/hotspot), [VNC server](network/vnc)...
+- [Network Services](network-features): [Samba/SMB share](network/samba), [HTTP server (retired)](network/http), [SSH/SFTP](network/ssh), [Hotspot](network/hotspot), [VNC server](network/vnc)...
:::
diff --git a/website/docs/07-apps/01-included-in-onion/tweaks.mdx b/website/docs/07-apps/01-included-in-onion/tweaks.mdx
index 4af3c541..fd36db25 100644
--- a/website/docs/07-apps/01-included-in-onion/tweaks.mdx
+++ b/website/docs/07-apps/01-included-in-onion/tweaks.mdx
@@ -186,12 +186,6 @@ It can be MainUI, [GameSwitcher](./game-switcher), [Retroarch](./retroarch) or [
-### FTP: File server...
-
-
FTP provides a method of transferring files between Onion and a PC, phone, or tablet. You'll need an FTP client installed on the other device.
-
-
-
### VNC: Screen share...
Share your MMP Screen to another device for demonstrations or applications or themes (The MMP does not have the performance to stream game footage through this feature).
diff --git a/website/docs/07-apps/03-network-features/01-samba-file-sharing.md b/website/docs/07-apps/03-network-features/01-samba-file-sharing.md
index 99e05e3f..2b4cf514 100644
--- a/website/docs/07-apps/03-network-features/01-samba-file-sharing.md
+++ b/website/docs/07-apps/03-network-features/01-samba-file-sharing.md
@@ -78,7 +78,9 @@ We've made controlling shares as easy as possible; from the "Samba: Network file
It's your Onion.. So let's get you setup with more (or less!) shares. We'll need to edit a file called smb.conf which is found in `/mnt/SDCARD/.tmp_update/config/smb.conf`.
-As always, there's many ways to access this file. You can use [FTP](https://github.com/OnionUI/Onion/wiki/FTP)/[HTTP](https://github.com/OnionUI/Onion/wiki/HTTP-fileserver) or pull out the SD card and do it the manual way.
+Use the reviewed [SSH / SFTP service](/docs/network/ssh), or remove the SD card
+and edit the file directly. The inherited FTP and HTTP servers are not shipped
+or started by BloomOS.
To add a share folder, just make a copy of and existing entry and modify the path/name, restart Samba in tweaks and you're ready to go - it'll automatically appear in your Samba menu in tweaks and be ready to access.
diff --git a/website/docs/07-apps/03-network-features/04-ftp.md b/website/docs/07-apps/03-network-features/04-ftp.md
index 3b6a6265..aaa84d0b 100644
--- a/website/docs/07-apps/03-network-features/04-ftp.md
+++ b/website/docs/07-apps/03-network-features/04-ftp.md
@@ -5,67 +5,13 @@ slug: /network/ftp
# FTP
-
-
-FTP provides a method of transferring files between your Miyoo Mini+ and other devices such as a PC/Phone/Tablet. You'll need an FTP client installed on the second device.
-
-
-## Features
-
-- File transfer
-
-- Debugging and troubleshooting
-
-
-## Enabling FTP access
-
-You can either use the master toggle to turn the FTP server on with your Right/Left arrows, or press A to enter the submenu.
-
-You'll find it in **Apps** › **Tweaks** › **Network** › **FTP: File server** and you'll get 2 options:
-
-1. **Enable** - Activate FTP access
-
-2. **Enable authentication** - Activate authentication (username/password)
-
-
-
-
-## Logging in
-
-:::note Default credentials
-**Username:** `onion`
-**Password:** `onion`
-*We're using a new auth system, user defined passwords will come in a future update.*
-:::
-
-Once you've activated your FTP server in Tweaks you'll now be able to connect using software such as FileZilla, CuteFTP, WinSCP, FireFTP. You'll also be able to use an SFTP client to transfer files securely if SSH is also enabled.
-
-You'll need the IP of the device, found below (**Tweaks** › **Network**)
-
-
-
-Exit tweaks to apply & start the FTP server
-
-
-## Disabling authentication
-
-Although this is not recommended on other peoples Wi-Fi, when you're at home on your own Wi-Fi this is absolutely fine.
-
-Head over to **Tweaks** › **Network** › **FTP**:
-
-
-
-:::info File corruption
-On some FTP clients you may need to alter settings or binary files will become damaged when they're transferred, FileZilla for example may need to change the setting shown below (**Transfer** › **Transfer type** › **Binary**)
-
-
-:::
-
-If you have authentication turned on, anonymous connections will fail.
-
-
-## Security
-
-:::caution Network security
-Although we've taken every precaution to offer as much security as possible, remember to keep your Onion safe. It is not recommended you use FTP on an insecure Wi-Fi network that is open or public as traffic is unencrypted, for this reason we strongly recommend you toggle FTP off when you're on the move!
-:::
+BloomOS does not ship or start the inherited FTP server. FTP sends credentials
+and file contents without transport encryption, and its whole-card write access
+does not meet BloomOS transfer-policy boundaries.
+
+Use the reviewed public-key-only [SSH / SFTP service](/docs/network/ssh) for
+remote file transfer. SFTP exposes only the policy-approved roots, keeps Saves
+read-only, and excludes credentials and update state. Removing an old SD card's
+`.ftpState` or `.authftpState` marker is optional: BloomOS ignores and retires
+both markers during compatibility reconciliation and stops any inherited
+`bftpd` process.
diff --git a/website/docs/07-apps/03-network-features/06-hotspot.md b/website/docs/07-apps/03-network-features/06-hotspot.md
index 0d9a9c4f..da50e762 100644
--- a/website/docs/07-apps/03-network-features/06-hotspot.md
+++ b/website/docs/07-apps/03-network-features/06-hotspot.md
@@ -4,7 +4,7 @@ slug: /network/hotspot
# Hotspot
-Your Miyoo Mini Plus just got a lot more portable. SSH, HTTP file server, and FTP on the go, no extra devices needed. Stay connected with ease, anytime, anywhere.
+Your Miyoo Mini Plus just got a lot more portable. Use the reviewed key-only SSH/SFTP service on the go, no extra devices needed. Stay connected with ease, anytime, anywhere.
Compatible with Netplay (best paired with [Easy Netplay](../multiplayer/easynetplay)
There are reports of issues with hotspot on firmware levels below `2023 05 05``.