diff options
author | Sven Gothel <[email protected]> | 2021-02-06 18:01:39 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2021-02-06 18:01:39 +0100 |
commit | 2d5d24d6b0816b5d74bb5ce7680287aa0a3c883b (patch) | |
tree | e81b159ab3349e0627ed31b5a7f81f3aee0f262f | |
parent | da21281f875a0df46bda4487ecba6ba768865545 (diff) |
BTDevice::updatePairingState: Reply PASSKEY/NUMERIC_COMPARE dummy value if !hasSMPIOCapability[Full,Binary]Input()
BT core requesting passkey or binary input w/o full or binary input caps is nonsense (bug?).
Reply with a default value off-thread ASAP.
Don't send event to user.
-rw-r--r-- | api/direct_bt/SMPTypes.hpp | 9 | ||||
-rw-r--r-- | src/direct_bt/BTDevice.cpp | 37 |
2 files changed, 39 insertions, 7 deletions
diff --git a/api/direct_bt/SMPTypes.hpp b/api/direct_bt/SMPTypes.hpp index 507321d0..e138789a 100644 --- a/api/direct_bt/SMPTypes.hpp +++ b/api/direct_bt/SMPTypes.hpp @@ -206,6 +206,15 @@ namespace direct_bt { return static_cast<uint8_t>(rhs); } std::string getSMPIOCapabilityString(const SMPIOCapability ioc) noexcept; + constexpr bool hasSMPIOCapabilityBinaryInput(const SMPIOCapability ioc) noexcept { + return ioc == SMPIOCapability::DISPLAY_YES_NO || + ioc == SMPIOCapability::KEYBOARD_ONLY || + ioc == SMPIOCapability::KEYBOARD_DISPLAY; + } + constexpr bool hasSMPIOCapabilityFullInput(const SMPIOCapability ioc) noexcept { + return ioc == SMPIOCapability::KEYBOARD_ONLY || + ioc == SMPIOCapability::KEYBOARD_DISPLAY; + } /** * Vol 3, Part H, 2.3.3 OOB authentication data diff --git a/src/direct_bt/BTDevice.cpp b/src/direct_bt/BTDevice.cpp index c0375792..fa0184e1 100644 --- a/src/direct_bt/BTDevice.cpp +++ b/src/direct_bt/BTDevice.cpp @@ -680,6 +680,7 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve const std::unique_lock<std::mutex> lock(mtx_pairing); // RAII-style acquire and relinquish via destructor jau::sc_atomic_critical sync(sync_pairing); + const SMPIOCapability iocap = pairing_data.ioCap_conn; const MgmtEvent::Opcode mgmtEvtOpcode = evt.getOpcode(); PairingMode mode = pairing_data.mode; bool is_device_ready = false; @@ -696,10 +697,32 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve claimed_state = pairing_data.state; } break; case SMPPairingState::PASSKEY_EXPECTED: - mode = PairingMode::PASSKEY_ENTRY_ini; + if( hasSMPIOCapabilityFullInput( iocap ) ) { + mode = PairingMode::PASSKEY_ENTRY_ini; + } else { + // BT core requesting passkey input w/o full input caps is nonsense (bug?) + // Reply with a default value '0' off-thread ASAP + DBG_PRINT("DBTDevice::updatePairingState.1a: state %s [ignored %s, sending dummy reply], mode %s, %s", + getSMPPairingStateString(pairing_data.state).c_str(), getSMPPairingStateString(claimed_state).c_str(), + getPairingModeString(pairing_data.mode).c_str(), evt.toString().c_str()); + claimed_state = pairing_data.state; // suppress + std::thread dc(&BTDevice::setPairingPasskey, sthis, 0); + dc.detach(); + } break; case SMPPairingState::NUMERIC_COMPARE_EXPECTED: - mode = PairingMode::NUMERIC_COMPARE_ini; + if( hasSMPIOCapabilityBinaryInput( iocap ) ) { + mode = PairingMode::NUMERIC_COMPARE_ini; + } else { + // BT core requesting binary input w/o input caps is nonsense (bug?) + // Reply with a default value 'true' off-thread ASAP + DBG_PRINT("DBTDevice::updatePairingState.1b: state %s [ignored %s, sending dummy reply], mode %s, %s", + getSMPPairingStateString(pairing_data.state).c_str(), getSMPPairingStateString(claimed_state).c_str(), + getPairingModeString(pairing_data.mode).c_str(), evt.toString().c_str()); + claimed_state = pairing_data.state; // suppress + std::thread dc(&BTDevice::setPairingNumericComparison, sthis, true); + dc.detach(); + } break; case SMPPairingState::OOB_EXPECTED: mode = PairingMode::OUT_OF_BAND; @@ -735,7 +758,7 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve if( smp_ltk.isResponder() ) { if( ( SMPKeyType::ENC_KEY & pairing_data.keys_resp_has ) == SMPKeyType::NONE ) { // no overwrite if( jau::environment::get().debug ) { - jau::PLAIN_PRINT(false, "[%s] DBTDevice::updatePairingState.0: ENC_KEY responder set", timestamp.c_str()); + jau::PLAIN_PRINT(false, "[%s] DBTDevice::updatePairingState.2a: ENC_KEY responder set", timestamp.c_str()); jau::PLAIN_PRINT(false, "[%s] - old %s", timestamp.c_str(), pairing_data.ltk_resp.toString().c_str()); jau::PLAIN_PRINT(false, "[%s] - new %s", timestamp.c_str(), smp_ltk.toString().c_str()); } @@ -748,7 +771,7 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve } else { if( ( SMPKeyType::ENC_KEY & pairing_data.keys_init_has ) == SMPKeyType::NONE ) { // no overwrite if( jau::environment::get().debug ) { - jau::PLAIN_PRINT(false, "[%s] DBTDevice::updatePairingState.0: ENC_KEY initiator set", timestamp.c_str()); + jau::PLAIN_PRINT(false, "[%s] DBTDevice::updatePairingState.2b: ENC_KEY initiator set", timestamp.c_str()); jau::PLAIN_PRINT(false, "[%s] - old %s", timestamp.c_str(), pairing_data.ltk_init.toString().c_str()); jau::PLAIN_PRINT(false, "[%s] - new %s", timestamp.c_str(), smp_ltk.toString().c_str()); } @@ -774,7 +797,7 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve } if( pairing_data.state != claimed_state ) { - DBG_PRINT("DBTDevice::updatePairingState.0: state %s -> %s, mode %s -> %s, ready %d, %s", + DBG_PRINT("DBTDevice::updatePairingState.3: state %s -> %s, mode %s -> %s, ready %d, %s", getSMPPairingStateString(pairing_data.state).c_str(), getSMPPairingStateString(claimed_state).c_str(), getPairingModeString(pairing_data.mode).c_str(), getPairingModeString(mode).c_str(), is_device_ready, evt.toString().c_str()); @@ -788,14 +811,14 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve std::thread dc(&BTDevice::processDeviceReady, this, sthis, evt.getTimestamp()); // @suppress("Invalid arguments") dc.detach(); } - DBG_PRINT("DBTDevice::updatePairingState.2: End Complete: state %s, %s", + DBG_PRINT("DBTDevice::updatePairingState.4: End Complete: state %s, %s", getSMPPairingStateString(claimed_state).c_str(), toString(false).c_str()); cv_pairing_state_changed.notify_all(); return true; } else { - DBG_PRINT("DBTDevice::updatePairingState.3: End Unchanged: state %s, %s, %s", + DBG_PRINT("DBTDevice::updatePairingState.5: End Unchanged: state %s, %s, %s", getSMPPairingStateString(pairing_data.state).c_str(), evt.toString().c_str(), toString(false).c_str()); } |