fix(openwrt): close TollGate free-access gap and mint URL mismatch
Two bugs found live against archy-x250-pa3: TollGate-3458 (the upstream tollgate-module-basic-go installer's own default AP, rebranded from OpenWrt's factory default wireless.default_radioN sections) was left bound to `network=lan` — wide open, unmetered, and sharing the router's admin LAN — because install_ipk() runs the upstream package's own uci-defaults scripts but nothing reconciled the AP they create with the separate `tollgate` network/bridge/firewall this project's own provision_ssid() sets up for the "archipelago" SSID. Fixed by folding any default_radioN section left on `lan` onto the `tollgate` network right after it's created. Separately, a caller-supplied mint_url with a trailing slash (https://mint.minibits.cash/Bitcoin/) got written byte-for-byte into accepted_mints[0].url, which tollgate-wrt string-compares exactly against a token's embedded (slash-less) mint URL — rejecting every otherwise-valid token as an "untrusted mint". Fixed by trimming trailing slashes before the value is used anywhere. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTdMfVJChCwCCYF1ZTRQLc
This commit is contained in:
committed by
archipelago
co-authored by
Claude Sonnet 5
parent
db52c06a72
commit
2947277205
@@ -240,10 +240,18 @@ impl RpcHandler {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let default_mint_url = format!("http://{}:{}", self.config.host_ip, LOCAL_MINT_PORT);
|
let default_mint_url = format!("http://{}:{}", self.config.host_ip, LOCAL_MINT_PORT);
|
||||||
|
// Trim trailing slash(es): tollgate-wrt matches a token's embedded
|
||||||
|
// mint URL against this value with an exact string compare, and
|
||||||
|
// Cashu wallets (Minibits included) encode mint URLs without a
|
||||||
|
// trailing slash. A stray slash here means every otherwise-valid
|
||||||
|
// token gets rejected as "untrusted mint" — confirmed live against
|
||||||
|
// archy-x250-pa3 2026-09-07 with a manually-entered
|
||||||
|
// "https://mint.minibits.cash/Bitcoin/".
|
||||||
let mint_url = p
|
let mint_url = p
|
||||||
.get("mint_url")
|
.get("mint_url")
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.unwrap_or(&default_mint_url)
|
.unwrap_or(&default_mint_url)
|
||||||
|
.trim_end_matches('/')
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let config = TollGateConfig {
|
let config = TollGateConfig {
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ pub async fn provision(router: &Router, config: &TollGateConfig) -> Result<()> {
|
|||||||
|
|
||||||
config::apply(router, config)?;
|
config::apply(router, config)?;
|
||||||
wifi::provision_ssid(router, config)?;
|
wifi::provision_ssid(router, config)?;
|
||||||
|
// Must come after provision_ssid (creates the `tollgate` network this
|
||||||
|
// folds the upstream installer's own default AP onto) — see
|
||||||
|
// regate_upstream_default_aps for why this is needed at all.
|
||||||
|
wifi::regate_upstream_default_aps(router)
|
||||||
|
.context("re-gate upstream tollgate-module-basic-go default AP(s)")?;
|
||||||
// Must come after provision_ssid (which creates br-tollgate) and before
|
// Must come after provision_ssid (which creates br-tollgate) and before
|
||||||
// the daemon restart below — config.json is only read at startup.
|
// the daemon restart below — config.json is only read at startup.
|
||||||
config::apply_daemon_config(router, config)
|
config::apply_daemon_config(router, config)
|
||||||
|
|||||||
@@ -118,6 +118,49 @@ fn provision_firewall(router: &Router) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fold the upstream `tollgate-module-basic-go` installer's own default
|
||||||
|
/// AP(s) onto the gated `tollgate` network.
|
||||||
|
///
|
||||||
|
/// `install::install_ipk` runs the package's `/etc/uci-defaults/*` first-boot
|
||||||
|
/// scripts itself (no real package manager to trigger them on OpenWrt 25.x —
|
||||||
|
/// see its doc comment). Those upstream scripts rebrand OpenWrt's
|
||||||
|
/// factory-default wifi sections (`wireless.default_radioN`, present on
|
||||||
|
/// every fresh install) to a `TollGate-<serial>` SSID, but only ever touch
|
||||||
|
/// the SSID — they leave `network` at its original `lan` binding. Nothing
|
||||||
|
/// else in this project's own provisioning (`provision_ssid` above) ever
|
||||||
|
/// looks at those sections; it only manages the separate `wireless.tollgate`
|
||||||
|
/// SSID it creates itself. Left alone, the result is two open SSIDs
|
||||||
|
/// broadcasting side by side: ours (gated by NoDogSplash) and upstream's
|
||||||
|
/// (wide open on `lan`, with a direct route to whatever's plugged into the
|
||||||
|
/// wired LAN port).
|
||||||
|
///
|
||||||
|
/// Confirmed live against archy-x250-pa3 2026-09-07: a client joining
|
||||||
|
/// "TollGate-3458" landed on `br-lan` with unrestricted WAN forwarding and
|
||||||
|
/// zero NoDogSplash involvement — free, unmetered internet, no captive
|
||||||
|
/// portal, on the router's own admin network.
|
||||||
|
///
|
||||||
|
/// Must run after `provision_network` (needs the `tollgate` network/bridge
|
||||||
|
/// to already exist) and before the network/wifi restart in
|
||||||
|
/// `restart_services` picks the new binding up.
|
||||||
|
pub fn regate_upstream_default_aps(router: &Router) -> Result<()> {
|
||||||
|
let sections = router.run_ok(
|
||||||
|
"uci show wireless 2>/dev/null | grep -o '^wireless\\.default_radio[0-9]*' | sort -u",
|
||||||
|
)?;
|
||||||
|
for section in sections.lines().map(str::trim).filter(|s| !s.is_empty()) {
|
||||||
|
let network_key = format!("{}.network", section);
|
||||||
|
let current = router.uci_get(&network_key).unwrap_or_default();
|
||||||
|
if current == "lan" {
|
||||||
|
info!(
|
||||||
|
"[{}] Re-gating upstream default AP {} (was network=lan) onto the tollgate network",
|
||||||
|
router.host, section
|
||||||
|
);
|
||||||
|
router.uci_set(&network_key, "tollgate")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
router.uci_commit(Some("wireless"))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the first available wireless radio device name (e.g. "radio0").
|
/// Return the first available wireless radio device name (e.g. "radio0").
|
||||||
fn detect_radio(router: &Router) -> Result<String> {
|
fn detect_radio(router: &Router) -> Result<String> {
|
||||||
let out =
|
let out =
|
||||||
|
|||||||
Reference in New Issue
Block a user