Skip to content

Commit daef514

Browse files
fix(ble): fail closed when bluez bonding state is unknown
1 parent dca2054 commit daef514

1 file changed

Lines changed: 27 additions & 21 deletions

File tree

libwebauthn/src/transport/ble/btleplug/pairing.rs

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ use super::Error;
1616
pub(crate) enum BondingState {
1717
Bonded,
1818
NotBonded,
19-
/// Bonding state could not be determined (non-bluez backend or DBus
20-
/// unreachable); the caller decides whether to proceed.
19+
/// State could not be determined; treated as not bonded.
2120
Unknown,
2221
}
2322

@@ -48,27 +47,22 @@ pub(crate) async fn check_bonded(peripheral: &Peripheral) -> BondingState {
4847
}
4948
}
5049

51-
/// Returns `Err(ConnectionFailed)` when the device is reachable but
52-
/// explicitly not bonded; falls through on `Unknown`.
50+
/// Refuses the link unless bluez confirms it is bonded.
5351
pub(crate) async fn enforce_bonded(peripheral: &Peripheral) -> Result<(), Error> {
54-
match check_bonded(peripheral).await {
55-
BondingState::Bonded => Ok(()),
56-
BondingState::Unknown => {
57-
warn!(
58-
"Could not verify LE Secure Connections bonding via bluez; \
59-
proceeding under OS pairing enforcement"
60-
);
61-
Ok(())
62-
}
63-
BondingState::NotBonded => {
64-
warn!(
65-
"BLE FIDO authenticator is not bonded with LE Secure Connections; \
66-
CTAP 2.2 §11.4 requires bonding. Pair the device via the OS \
67-
(e.g. `bluetoothctl pair <ADDR>`) before retrying."
68-
);
69-
Err(Error::ConnectionFailed)
70-
}
52+
bonded_or_refused(check_bonded(peripheral).await)
53+
}
54+
55+
fn bonded_or_refused(state: BondingState) -> Result<(), Error> {
56+
if state == BondingState::Bonded {
57+
return Ok(());
7158
}
59+
warn!(
60+
?state,
61+
"BLE FIDO authenticator link is not confirmed bonded with LE Secure \
62+
Connections; CTAP 2.2 §11.4 requires bonding. Pair the device via the OS \
63+
(e.g. `bluetoothctl pair <ADDR>`) before retrying."
64+
);
65+
Err(Error::ConnectionFailed)
7266
}
7367

7468
/// btleplug doesn't expose the adapter index, so we walk the bluez
@@ -109,3 +103,15 @@ fn query_bluez_bonded(address: BDAddr) -> Result<(bool, bool), String> {
109103

110104
Err(format!("device {address} not found in bluez ObjectManager"))
111105
}
106+
107+
#[cfg(test)]
108+
mod tests {
109+
use super::*;
110+
111+
#[test]
112+
fn only_confirmed_bonded_proceeds() {
113+
assert!(bonded_or_refused(BondingState::Bonded).is_ok());
114+
assert!(bonded_or_refused(BondingState::NotBonded).is_err());
115+
assert!(bonded_or_refused(BondingState::Unknown).is_err());
116+
}
117+
}

0 commit comments

Comments
 (0)