mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 19:27:03 +01:00
The nine network-curfew functions -- the per-UID iptables allow-list that cuts every app outside $NIGHT_WHITELIST off the network overnight -- move into curfew_net.sh. NET_BUILT stays in the enforcer: both files write it, so it is a genuine shared global rather than a seam violation. Placed as a FLAT sibling, not under lib/. deploy.sh pushes phone scripts into one directory, so a lib/ path would simply not exist on the device; dns_iptables.sh and tether_iptables.sh sit beside their enforcers for the same reason. Added to BOTH deploy lists, and deliberately not to the chmod list -- sourced files need no exec bit there, matching the other two. 41 assertions, 60/60 lines, 17 mutations all killed. The one that matters most flips the 10000-19999 REJECT to ACCEPT, which would silently disable the entire cut-off while leaving a chain that looks populated. The suite also asserts rule ORDER, not just presence: every ACCEPT must precede that REJECT, or the whitelist blocks the very apps it exists to permit. night_uids and fill_net_chain are reported as non-verbatim by verify_shell_split.sh, correctly: both ended in `done < file`, a line kcov instruments and bash never reports, which alone held the file at 96.77%. Both are now piped. Neither loop reads stdin internally, so the subshell is immaterial -- unlike pull_apks in backup_capture.sh, where the same change would reintroduce a known bug. Behaviour was checked rather than assumed: night_uids emits the same uids, and fill_net_chain emits an identical 11-rule sequence, diffed against the pre-split bodies. UNVERIFIED ON DEVICE -- joins tether_enforcer.sh and dns_enforcer.sh. Over-cap count 21 -> 20. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
171 lines
4.1 KiB
Bash
Executable File
171 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# lib/tests/curfew_net_harness.sh — staging and stubs for the curfew_net.sh
|
|
# tests.
|
|
#
|
|
# Sourced, not executed. Unlike the monitor tests, the stubs here go on PATH:
|
|
# curfew_net.sh calls iptables, ip6tables and pm as real binaries, so the
|
|
# process boundary is where the fake has to sit. Modelled on
|
|
# dns_iptables_harness.sh, which stubs the same two firewall binaries.
|
|
#
|
|
# The stub records every call in order, which is what makes the rule ordering
|
|
# assertable — the ACCEPT rules must precede the 10000-19999 REJECT or the
|
|
# whitelist is meaningless.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
readonly SCRIPT_DIR
|
|
readonly PHONE_DIR="${SCRIPT_DIR}/../.."
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
_t_pass() {
|
|
PASS=$((PASS + 1))
|
|
printf ' OK: %s\n' "$1"
|
|
}
|
|
|
|
_t_fail() {
|
|
FAIL=$((FAIL + 1))
|
|
printf ' FAIL: %s\n' "$1"
|
|
}
|
|
|
|
_t_eq() {
|
|
local want="$1" got="$2" what="$3"
|
|
if [[ "$got" == "$want" ]]; then
|
|
_t_pass "$what"
|
|
else
|
|
_t_fail "$what (want '${want}', got '${got}')"
|
|
fi
|
|
}
|
|
|
|
RUN="$(mktemp -d)"
|
|
trap 'rm -rf "${RUN}"' EXIT
|
|
mkdir -p "${RUN}/app" "${RUN}/bin" "${RUN}/state" "${RUN}/ipt"
|
|
|
|
cp "${PHONE_DIR}/curfew_net.sh" "${RUN}/app/"
|
|
|
|
# --- iptables/ip6tables stub ------------------------------------------------
|
|
#
|
|
# Models a per-binary chain flag, a rule list and the OUTPUT jump count. Every
|
|
# call is logged so ordering can be asserted. Failure injection mirrors
|
|
# dns_iptables_harness.sh: a test touches fail_<op> to make that operation
|
|
# report failure, which is how the error returns become reachable.
|
|
cat >"${RUN}/bin/iptables" <<'STUB'
|
|
#!/usr/bin/env bash
|
|
bin="$(basename "$0")"
|
|
store="${IPT_STATE}/${bin}"
|
|
mkdir -p "$store"
|
|
rules="${store}/rules"
|
|
touch "$rules"
|
|
|
|
# curfew_net always calls through iptw, which prepends `-w 2`. Drop it so the
|
|
# case below matches on the real operation.
|
|
[[ "$1" == "-w" ]] && shift 2
|
|
|
|
printf '%s %s\n' "$bin" "$*" >>"${IPT_STATE}/calls.log"
|
|
|
|
_fails() { [[ -f "${IPT_STATE}/fail_$1" ]]; }
|
|
|
|
_jumps_file="${store}/jumps"
|
|
[[ -f "$_jumps_file" ]] || echo 0 >"$_jumps_file"
|
|
|
|
case "$1" in
|
|
-L) [[ -f "${store}/chain" ]] && exit 0 || exit 1 ;;
|
|
-N)
|
|
_fails N && exit 1
|
|
touch "${store}/chain"
|
|
exit 0
|
|
;;
|
|
-F)
|
|
_fails F && exit 1
|
|
: >"$rules"
|
|
exit 0
|
|
;;
|
|
-X)
|
|
rm -f "${store}/chain"
|
|
exit 0
|
|
;;
|
|
-A)
|
|
shift
|
|
printf -- '%s\n' "$*" >>"$rules"
|
|
exit 0
|
|
;;
|
|
-I)
|
|
_fails I && exit 1
|
|
read -r n <"$_jumps_file"
|
|
echo $((n + 1)) >"$_jumps_file"
|
|
exit 0
|
|
;;
|
|
-D)
|
|
# Succeeds once per existing jump so the de-dupe loop terminates.
|
|
read -r n <"$_jumps_file"
|
|
if ((n > 0)); then
|
|
echo $((n - 1)) >"$_jumps_file"
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
;;
|
|
esac
|
|
exit 0
|
|
STUB
|
|
chmod +x "${RUN}/bin/iptables"
|
|
cp "${RUN}/bin/iptables" "${RUN}/bin/ip6tables"
|
|
|
|
# `pm list packages -U` output, seeded per test via PM_FIXTURE.
|
|
cat >"${RUN}/bin/pm" <<'STUB'
|
|
#!/usr/bin/env bash
|
|
[[ -f "${PM_FIXTURE}" ]] && cat "${PM_FIXTURE}"
|
|
exit 0
|
|
STUB
|
|
chmod +x "${RUN}/bin/pm"
|
|
|
|
export IPT_STATE="${RUN}/ipt"
|
|
export PM_FIXTURE="${RUN}/state/pm.txt"
|
|
export PATH="${RUN}/bin:${PATH}"
|
|
|
|
# --- ambient globals the library reads from config.sh / the enforcer --------
|
|
|
|
STATE_DIR="${RUN}/state"
|
|
CURFEW_NET_IPT_CHAIN="FOCUS_CURFEW_NET"
|
|
CURFEW_NET_UID_CACHE="${RUN}/state/curfew_uids.cache"
|
|
CURFEW_NET_REASSERT_INTERVAL=1
|
|
CURFEW_NET_ENABLED=1
|
|
NET_BUILT=""
|
|
|
|
log() { printf '%s\n' "$*" >>"${RUN}/state/log"; }
|
|
|
|
# shellcheck source=../../curfew_net.sh
|
|
. "${RUN}/app/curfew_net.sh"
|
|
|
|
_reset_ipt() {
|
|
rm -rf "${RUN}/ipt"
|
|
mkdir -p "${RUN}/ipt"
|
|
}
|
|
|
|
# Make the next run report the given iptables operation as failing.
|
|
_fail_op() {
|
|
touch "${RUN}/ipt/fail_$1"
|
|
}
|
|
|
|
_clear_fail() {
|
|
rm -f "${RUN}/ipt/fail_$1"
|
|
}
|
|
|
|
# Pre-seed the chain as existing with N stale OUTPUT jumps, the lock-race
|
|
# state ensure_net_chain's de-dupe loop exists to clean up.
|
|
_seed_jumps() {
|
|
local bin="$1" count="$2"
|
|
mkdir -p "${RUN}/ipt/${bin}"
|
|
touch "${RUN}/ipt/${bin}/chain"
|
|
echo "$count" >"${RUN}/ipt/${bin}/jumps"
|
|
}
|
|
|
|
# Rules recorded for a binary, one per line.
|
|
_rules_of() {
|
|
cat "${RUN}/ipt/$1/rules" 2>/dev/null || printf ''
|
|
}
|
|
|
|
_calls() {
|
|
cat "${RUN}/ipt/calls.log" 2>/dev/null || printf ''
|
|
}
|