mirror of
https://github.com/RoganDawes/P4wnP1_aloa.git
synced 2025-03-28 18:41:46 +01:00
Set bluetooth back to SSP, to make HS and thus NAP work (no PIN)
This commit is contained in:
parent
61e8eec55f
commit
5532463602
@ -10,6 +10,8 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -20,41 +22,131 @@ const (
|
||||
type BtService struct {
|
||||
RootSvc *Service
|
||||
|
||||
ServiceAvailable bool
|
||||
serviceAvailable bool
|
||||
Controller *bluetooth.Controller
|
||||
BrName string
|
||||
bridgeIfDeployed bool
|
||||
|
||||
Agent *bluetooth.DefaultAgent
|
||||
|
||||
serviceAvailableLock *sync.Mutex
|
||||
}
|
||||
|
||||
func NewBtService(rootService *Service) (res *BtService) {
|
||||
//Notes: If a bluetooth controller could be found with `bluetooth.FindFirstAvailableController()`
|
||||
// this also means that the bluetoothd is running, as the Bluez mgmt-api is used to check for controllers
|
||||
|
||||
// P4wnP1 doesn't depend on late starting systemd services like DBus, bluetoothd etc.
|
||||
// In order to assure that Bluetooth functionality is present, the P4wnP1 systemd service would have to depend
|
||||
// on such "late starting" services. This again means the P4wnP1 daemon would load very late and functionality like
|
||||
// USB gadgets wouldn't work till service the P4wnP1 systemd service gets started. Tests with current Kali releases have
|
||||
// shown that P4wnP1 is up and reachable network after about 20 to 30 seconds.
|
||||
// If the P4wnP1 systemd service is changed to depend on bluetooth.service this duration increases up to 2 minutes,
|
||||
// which is NOT ACCEPTABLE.
|
||||
// On the other hand, access to the bluez-stack and the hci device (if present) is already possible some seconds
|
||||
// after the P4wnP1 service has started (doesn't take 2 minutes).
|
||||
// To deal with that, the bluetooth subsystem keeps retrying to find a working bluetooth adapter till "retryTimeout"
|
||||
// is reached (the argument is handed in to NewBtService). If the hci adapter gets deployed after some seconds (as it
|
||||
// happens in my tests) this means service startup of P4wnP1 increases by this duration (about 6 seconds in tests)
|
||||
// On a system with a mis-configured bluetooth stack or with missing bluetooth hardware (Pi0 without WiFi/Bluetooth)
|
||||
// this would mean P4wnP1 service startup consumes the full retryTime (shouldn't be the case, as we target a RPi0W
|
||||
// with a custom build Kali image, which assures correct bluetooth stack setup; Pi0 without WiFi isn't supported).
|
||||
//
|
||||
// The current behavior could be changed, if NewBtService gets wrapped into a go-routine. The shortcoming would be,
|
||||
// that every call to to BtService functions (like StartNap) would fail, even if the missing adapter could show up some
|
||||
// seconds later.
|
||||
//
|
||||
// A polished future solution would be, to combine creation of Bluetooth SubSystem and initial configuration deployment
|
||||
// in a go routine and let RPC calls relying on bluetooth sub system fail, till bluetooth is usable. This would mean that
|
||||
// an event has to be PUSHED to the webclient, once bluetooth is usable.
|
||||
|
||||
|
||||
|
||||
func NewBtService(rootService *Service, retryTimeout time.Duration) (res *BtService) {
|
||||
res = &BtService{
|
||||
RootSvc: rootService,
|
||||
Agent: bluetooth.NewDefaultAgent("4321"),
|
||||
Agent: bluetooth.NewDefaultAgent("1337"),
|
||||
BrName: BT_ETHERNET_BRIDGE_NAME,
|
||||
serviceAvailableLock: &sync.Mutex{},
|
||||
}
|
||||
|
||||
// ToDo Check if bluetooth service is loaded
|
||||
if c, err := bluetooth.FindFirstAvailableController(); err == nil {
|
||||
res.ServiceAvailable = true
|
||||
res.Controller = c
|
||||
} else {
|
||||
res.ServiceAvailable = false
|
||||
return
|
||||
}
|
||||
log.Println("Starting Bluetooth sub system...")
|
||||
if err := CheckBluezVersion(); err != nil {
|
||||
fmt.Println(err)
|
||||
res.ServiceAvailable = false
|
||||
log.Println(err)
|
||||
|
||||
res.setServiceAvailable(false)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
timeStart := time.Now()
|
||||
for timeSinceStart := time.Since(timeStart); !res.serviceAvailable && (timeSinceStart < retryTimeout); timeSinceStart = time.Since(timeStart) {
|
||||
if c, err := bluetooth.FindFirstAvailableController(); err == nil {
|
||||
res.setServiceAvailable(true)
|
||||
res.Controller = c
|
||||
log.Printf("... bluetooth controller found '%s' after %v\n", res.Controller.DBusPath, timeSinceStart)
|
||||
} else {
|
||||
log.Printf("Re-check bluetooth adapter existence %v\n", timeSinceStart)
|
||||
res.setServiceAvailable(false)
|
||||
}
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
if !res.serviceAvailable {
|
||||
log.Printf("No bluetooth adapter found after %v\n", retryTimeout)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (bt *BtService) setServiceAvailable(val bool) {
|
||||
bt.serviceAvailableLock.Lock()
|
||||
defer bt.serviceAvailableLock.Unlock()
|
||||
bt.serviceAvailable = val
|
||||
}
|
||||
|
||||
func (bt *BtService) IsServiceAvailable() bool {
|
||||
bt.serviceAvailableLock.Lock()
|
||||
defer bt.serviceAvailableLock.Unlock()
|
||||
return bt.serviceAvailable
|
||||
}
|
||||
|
||||
|
||||
// Notes: On Bluetooth settings
|
||||
// P4wnP1 is meant to run headless, which has influence on Pairing mode. There's legacy pairing (outdated and insecure)
|
||||
// which allows requesting a PIN from a remote device which wants to connect. The new Pairing mode is Secure Simple Pairing
|
||||
// (SSP) which add in dynamic key creation on pairing, without static PINs. There are different ways two devices could be paired,
|
||||
// the way is chosen depending on the capabilities of both devices. IT ISN'T POSSIBLE TO REQUEST A PREDEFINED PIN WITH
|
||||
// SECURE SIMPLE PAIRING. Bonding (=Pairing) is handled with a random passkey or in just works mode.
|
||||
// As P4wnP1 could not display a passkey or request user input for a confirmation (assuming interactive access solutions
|
||||
// like webclient, cli_client or ssh aren't always used), we have to fall back to "just works" mode if we want to use SSP.
|
||||
// Even if a static PIN is a security issue, using just works is even more insecure.
|
||||
// On the other hand, the idea to disable SSP didn't work out either, because this won't allow to set the broadcom bluetooth
|
||||
// adapter to high speed. Not having high speed enabled, ultimately results in connection issues for BNEP usage
|
||||
// (in fact, if a NAP is turned on without high speed, a remote device is able to pair and connect, even to receive a DHCP
|
||||
// lease from the server. The latter indicates that th IP connection (layer 3) is working, but follow up traffic doesn't
|
||||
// work (neither on layer 3 -l ike ICMP requests, nor on layer 4 - like TCP based SSH connections)
|
||||
// The behavior of not fully working connections has been observed using a Samsung Android phone as remote device. It has
|
||||
// not been confirmed that connection issues exist on other devices. Anyways, not having a common device working means
|
||||
// PIN based pairing without SSP isn't an option.
|
||||
// In result SSP has to be turned on in "just works" mode (we describe P4wnP1 as a device with no input and no outpu capabilities).
|
||||
//
|
||||
// As P4wnP1 IS NOT DESIGNED WITH SECURITY IN MIND (at least no self-protection), a new issue arises:
|
||||
//
|
||||
// As soon as a bluetooth is turned on and set to be discoverable and pairable, EVERY REMOTE DEVICE IS ACCEPTED TO CONNECT AND PAIR.
|
||||
// (While WiFi access could at least be protected with WPA2). Neither the the WebClient, nor the RPC server deploy any kind of
|
||||
// MitM protection, access restriction or other security measures to protect themselves from other ways of compromise.
|
||||
// A solution has to be found to deal with that issue (in a headless way)! Possible ideas
|
||||
// - allow disabling/enabling PAIRING on demand by webclient / clie
|
||||
// - use limited PAIRING (timeout till pairing is disabled again) on boot, f.e. with a 30 second time window. Disable pairing
|
||||
// as soon as one device connected. This till leaves a race condition
|
||||
//
|
||||
// For now: Pairing in "just works" mode is always on!
|
||||
|
||||
// ToDo: Move all controller specific tasks to controller
|
||||
func (bt *BtService) StartNAP() (err error) {
|
||||
if !bt.ServiceAvailable {
|
||||
|
||||
if !bt.IsServiceAvailable() {
|
||||
return bluetooth.ErrBtSvcNotAvailable
|
||||
}
|
||||
log.Println("Bluetooth: starting NAP...")
|
||||
@ -69,14 +161,15 @@ func (bt *BtService) StartNAP() (err error) {
|
||||
}
|
||||
|
||||
// Register custom agent bt-agent with "No Input, No Output" capabilities
|
||||
// Note: This results in "just works" mode with no MitM protection (see notes above)
|
||||
if err = bt.Agent.Start(toolz.AGENT_CAP_NO_INPUT_NO_OUTPUT); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Disable simple secure pairing to make PIN requests work
|
||||
// SSP and HS enabled, this disables PIN requests but is needed for NAP to work (see comments above)
|
||||
bt.Controller.SetPowered(false)
|
||||
bt.Controller.SetSSP(true) //NAP doesn't work well without SSP
|
||||
bt.Controller.SetHighSpeed(true) // Enable high speed mode
|
||||
bt.Controller.SetSSP(true) //Couldn't use legacy mode (no Secure Simple Pairing, but PIN based pairing), otherwise HighSpeed couldn't be enabled
|
||||
bt.Controller.SetHighSpeed(true) // Enable high speed mode, yeah (without high speed, NAP connections don't work as intended)
|
||||
bt.Controller.SetPowered(true)
|
||||
|
||||
// Configure adapter
|
||||
@ -99,6 +192,8 @@ func (bt *BtService) StartNAP() (err error) {
|
||||
}
|
||||
err = bt.Controller.SetPairable(true)
|
||||
|
||||
time.Sleep(time.Second) //give some time before registering NAP to SDP
|
||||
|
||||
// Enable PAN networking for bridge
|
||||
nw, err := toolz.NetworkServer(bt.Controller.DBusPath)
|
||||
if err != nil {
|
||||
@ -118,7 +213,7 @@ func (bt *BtService) StartNAP() (err error) {
|
||||
}
|
||||
|
||||
func (bt *BtService) StopNAP() (err error) {
|
||||
if !bt.ServiceAvailable {
|
||||
if !bt.IsServiceAvailable() {
|
||||
return bluetooth.ErrBtSvcNotAvailable
|
||||
}
|
||||
log.Println("Bluetooth: stopping NAP...")
|
||||
@ -262,7 +357,7 @@ func CheckBluezVersion() (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Bluez %d.%d found (minimum needed %d.%d)\n", major, minor, BT_MINIMUM_BLUEZ_VERSION_MAJOR, BT_MINIMUM_BLUEZ_VERSION_MINOR)
|
||||
log.Printf("Bluez %d.%d found (minimum needed %d.%d)\n", major, minor, BT_MINIMUM_BLUEZ_VERSION_MAJOR, BT_MINIMUM_BLUEZ_VERSION_MINOR)
|
||||
if major > BT_MINIMUM_BLUEZ_VERSION_MAJOR {
|
||||
return nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user