Talk:TIP Bluetooth Proximity Monitor

From Gentoo Linux Wiki

Jump to: navigation, search

I suppose, that using sudo to start/kill xscreensaver and hcitool is better than

  1. chmod +s /usr/bin/hcitool

Simply edit your /etc/sudoers

Am I right? yes

Contents

[edit] KDE

Try this, if you are using kde:

 START_CMD='true'
 FAR_CMD='dcop kdesktop KScreensaverIface lock'
 NEAR_CMD='dcop kdesktop KScreensaverIface quit'


[edit] Phone off.

I have edited the script so that it works when the phone is switched off. I also used sudo to save logging in as root.

Here is my code:


File: ~/btproximity
#!/bin/sh

DEVICE="00:00:00:00:00:00"
CHECK_INTERVAL=2
THRESHOLD=-7
PID=0
START_CMD='/usr/bin/xscreensaver -nosplash'
FAR_CMD='/usr/bin/xscreensaver-command -lock'
NEAR_CMD='/bin/killall xscreensaver'

HCITOOL="sudo /usr/bin/hcitool"
DEBUG="/dev/null"

connected=0

function msg {
    echo "$1" >> $DEBUG
}

function check_connection {
    connected=0;
    found=0

    for s in `$HCITOOL con`; do
        if [[ "$s" == "$DEVICE" ]]; then
            found=1;
        fi
    done
    if [[ $found == 1 ]]; then
        connected=1;
    else
       msg 'Attempting connection...'
        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
            msg 'Connected.'
            connected=1;
        else
            connected=0;
        fi
    fi
}

function check_xscreensaver {
    PID=`ps -C xscreensaver --no-heading | awk '{ print $1 }'`
    if [ "$PID" == "" ];  then
        $START_CMD &
    fi
}

name=`$HCITOOL name $DEVICE`
msg "Monitoring proximity of \"$name\" [$DEVICE]";

state="near"
while /bin/true; do

    check_xscreensaver
    check_connection

    if [[ $connected -eq 1 ]]; then
        rssi=`$HCITOOL rssi $DEVICE | sed -e 's/RSSI return value: //g'`

        if (( $rssi <= $THRESHOLD )); then
            if [[ "$state" == "near" ]]; then
                msg "*** Device \"$name\" [$DEVICE] has left proximity"
                state="far"
                $FAR_CMD > /dev/null 2>&1
            fi
        else
            if [[ "$state" == "far" ]]; then
                msg "*** Device \"$name\" [$DEVICE] is within proximity"
                state="near"
                $NEAR_CMD > /dev/null 2>&1
                $START_CMD &
            fi
        fi
        msg "state = $state, RSSI = $rssi, PID = $PID"

    else
        if [[ "$state" == "near" ]]; then
            msg "*** Device \"$name\" [$DEVICE] has been disconnected"
            state="far"
            $FAR_CMD > /dev/null 2>&1
        fi
    fi

    sleep $CHECK_INTERVAL
done
 

It probably wouldn't be too hard to patch xscreensaver to include -unlock functionality, but for *practical* purposes, perhaps one might consider finding a more secure/bulletproof fashion of patching then just "-unlock". -unlock would be the hackish solution; Here's an idea:

 $hash = randomly_generated_hex_hash()
 xscreensaver-command -lock-with-hash=$hash
 ## which may or may not be "432F36EA4B3"
 xscreensaver-command -unlock-with-hash=$hash

this may not be *perfectly* secure, since the hash may be kept in plain text in the script's memory, but it'll provide at least a mildly secure solution. One might even consider using crypt() for extra security. EDIT: To anyone actually _planning_ on patching, I shouldn't need to explain why "-unlock" as a practical solution is a bad idea, but generally it's because permissions aren't checked, and even if they are, it's not exactly a chore to run a command for a user that isn't you. The point isn't to make it unhackable, the point is to keep people from unlocking your screen with a single command for shits and giggles, excuse my french.


This script is great. Thanks!
But if I swiched off my phone I must wait a few seconds befor xscreensaver starts. 10 seconds are a long time ;)
The script search for my device, but there must be a timeout befor it defenetly says the device is not present
Is it possible to change that timeout?

[edit] Distance w/ RSSI?

Hello,

This code is fantastic.

I also want to know the exact distance of my mobile form my pc in feets, using RSSI. How can I do it? Do you have some code for it?


Thanks,

Sriharsha



Sriharsha:
As far as I know, you can't calculate REAL distance with RSSI, since RSSI is just a signal strength, and signal strength may vary from phone to phone.


-Ben (author)

[edit] Running as root

FWIW Ubuntu ACPI scripts use the following to figure out which user is running the X session, and control the screen saver:

  PATH="$PATH:/usr/bin/X11"
  user=`who| grep -m1 " :0" | awk '{print $1}'`
  export XAUTHORITY=/home/$user/.Xauthority
  export DISPLAY=:0
  su - $user -c "xscreensaver-command -deactivate"

I suppose you can use this to avoid SUIDing hcitool.

[edit] Works but...

This ingenious script actually works, but unfortunately, the signal strength of my mobile phone (Samsung SHG-D500) seems to fluctuate a lot. One moment, when sitting in my in front of my PC, hcitool rssi <addr> returns 0, a few seconds later it returns -7.

Even with THRESHOLD set to -15, I get accidental screen locks when just sitting in front of my computer. Maybe I just have the wrong phone for this....

--raptux 19:06, September 7, 2005 (GMT)

My Nokia 6600 exibits the same problem I get 10 rssi=0 then it goes -1 -2 ... -7 and reconnects.

-- nivw 14:29, Feb 2, 2006

Hello,

With my Samsung E530 the RSSI value is also not very stable... I'm wondering if it isn't a general problem that is independant of the phone/device ?

Maybe one could combine the RSSI and LQ (Link Quality) values of determine if the device is near or far ? I'm not an expert and I would appreciate your opinions on this !

Another problem that I have with a Dell X510 (Axim) PDA : when I connect to that device, the connection always times out after ~10 seconds ! Is there something I can do ? Does it come from Windows Mobile or from the hardware ? Do you have any ideas ?

Thank you in advance !

Sofia

Hey, Same Problem as Sofia, Windows Mobile 6 HTC S71. hcitool cc <mac> will connect then drop after a few seconds, even when hcitool auth <mac> is called.

Cheers, Tag

[edit] gnome-screensaver

Code: CMD Changes
FAR_CMD='/usr/bin/gnome-screensaver-command --lock'

NEAR_CMD='/usr/bin/gnome-screensaver-command --deactivate'


Full Code (Locks when device turned off / out of range, Unlocks gnome-screensaver without password when device re-enters range):

Code: BTProx.sh
#!/bin/bash
#set -o verbose sh -v
# Copied from Steven on http://gentoo-wiki.com/Talk:TIP_Bluetooth_Proximity_Monitor
# Modified By Jamie Paton <jamie.paton@googlemail.com>


# These are the sections you'll need to edit

 # You'll need to use the MAC address of your phone here
#Use "hcitool scan" to find the MAC of your device
DEVICE="00:38:13:59:43:12"

# How often to check the distance between phone and computer in seconds
CHECK_INTERVAL=10

# The RSSI threshold at which a phone is considered far or near
THRESHOLD=-8

# The command to run when your phone gets too far away
FAR_CMD='/usr/bin/gnome-screensaver-command --activate'

# The command to run when your phone is close again
#NEAR_CMD='/opt/gnome/bin/gnome-screensaver-command --poke'
NEAR_CMD='/usr/bin/gnome-screensaver-command --deactivate'

HCITOOL="sudo /usr/bin/hcitool"
STARTX_PID=0
DEBUG="/tmp/btproximity.log"

connected=0
state="far"

function msg {
    echo "$1" >> "$DEBUG"
    echo "$1"
}

function check_connection {
    connected=0;
    found=0
    for s in `$HCITOOL con`; do
        if [[ "$s" == "$DEVICE" ]]; then
            found=1;
        fi
    done
    if [[ $found == 1 ]]; then
        connected=1;
    else
       msg 'Attempting connection...'
        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
            msg 'Connected'
            connected=1;
        else
                if [ -z "`l2ping -c 2 -t 5 -i $DEVICE 2>&1`" ]; then
                        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
                            msg 'Ping is good!'
                            connected=1;
                        else
                        msg "ERROR: Could not connect to device $DEVICE."
                        connected=0;
                        fi
                fi
        fi
    fi
if [[ $connected -eq 0 ]]; then
	$FAR_CMD > /dev/null 2>&1
	state="far"
     fi

}

check_connection

while [[ $connected -eq 0 ]]; do
    check_connection
    sleep 10
done

name=`$HCITOOL name $DEVICE`
msg "Monitoring proximity of \"$name\" [$DEVICE]";

while /bin/true; do
	state="far"
    check_connection

    if [[ $connected -eq 1 ]]; then
        rssi=$($HCITOOL rssi $DEVICE | sed -e 's/RSSI return value: //g')

        if [[ $rssi -le $THRESHOLD ]]; then
            if [[ "$state" == "near" ]]; then
                msg "*** Device \"$name\" [$DEVICE] has left proximity"
                state="far"
                $FAR_CMD > /dev/null 2>&1
            fi
        else
            if [[ "$state" == "far" && $rssi -ge $[$THRESHOLD+2] ]]; then
                msg "*** Device \"$name\" [$DEVICE] is within proximity"
                state="near"
                $NEAR_CMD > /dev/null 2>&1
                STARTX_PID=$(pgrep startx)
            fi
        fi
        msg "state = $state, RSSI = $rssi"
    fi
    sleep $CHECK_INTERVAL
done 

[edit] making it better

Work grate here.

Hay, According to a post at the BlueZ ML , I see that python may be used to write an event driven program. then there wouldn't be a need to pool the BT device: post

But I dont know python :-(

[edit] Security concerns

There's a very subtle security issue here.

Firstly, there's an unsubtle issue. Unless the link is encrypted, anyone can pretend to be your phone by faking the Bluetooth address. So, first step, make sure the link is encrypted (or simply don't trust the RSSI unless the link is encrypted and fall back to some secondary mechanism such as a timeout).

Then there's the subtle issue. RSSI is probably estimated by examining on all packets the device receives, not just those that contain data. Unfortunately, only the data is encrypted. This means an attacker could inject high strength packets with no payload onto link while you're out of range. This might be enough to cause your screen to unlock.

So, second step, don't use automatic unlocking if you want any semblence of security.

Even this second step isn't sufficient. An attacker could inject periodic high strength packets while the screen is unlocked and thus prevent the screen from locking as you walk away.

So, I wouldn't recommend this as the sole screen locking mechanism for any high security application.

Coupling this method with a normal screen saver timeout might form a good second line of defence. If you walk away from your screen without locking it then if there's no attacker present the screen will lock faster than without the RSSI checking. Similarly, if an attacker is present and you forget to lock your screen then you're no worse of than if you'd just had a timer (which is a method that suits most people just fine).

-- Steven (a Bluetooth firmware engineer using guest access) 19:27, 7 February 2006 (GMT)

Here are my additions:

  • I use it to log on and off from the home and pcs
  • I set a margin so FAR is when below -6 and Near is above -4 , so if I am standing at the door , my pc wont go nutch.
  • I ping the cellular if hcitool cc doesnt work. it seems to help. u need to add l2ping to the sudo for that user.


Code: btproximity.sh
#!/bin/bash
#set -o verbose sh -v
DEVICE="00:0E:6D:45:97:A1"
CHECK_INTERVAL=2
THRESHOLD=-6
STARTX_PID=0
FAR_CMD='/bin/kill -9 $STARTX_PID'
NEAR_CMD='/usr/bin/startx -- :1'
HCITOOL="sudo /usr/bin/hcitool"
DEBUG="~/log/btproximity.log"

connected=0

function msg {
    echo "$1" #>> "$DEBUG"
}

function check_connection {
    connected=0;
    found=0
    for s in `$HCITOOL con`; do
        if [[ "$s" == "$DEVICE" ]]; then
            found=1;
        fi
    done
    if [[ $found == 1 ]]; then
        connected=1;
    else
       msg 'Attempting connection...'
        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
            msg 'Connected.'
            connected=1;
        else
                if [ -z "`l2ping -c 2 $DEVICE 2>&1`" ]; then
                        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
                            msg 'Connected.'
                            connected=1;
                        else
                        msg "ERROR: Could not connect to device $DEVICE."
                        connected=0;
                        fi
                fi
        fi
    fi
}

check_connection

while [[ $connected -eq 0 ]]; do
    check_connection
    sleep 3
done

name=`$HCITOOL name $DEVICE`
msg "Monitoring proximity of \"$name\" [$DEVICE]";

state="near"
while /bin/true; do

    check_connection

    if [[ $connected -eq 1 ]]; then
        rssi=$($HCITOOL rssi $DEVICE | sed -e 's/RSSI return value: //g')

        if [[ $rssi -le $THRESHOLD ]]; then
            if [[ "$state" == "near" ]]; then
                msg "*** Device \"$name\" [$DEVICE] has left proximity"
                state="far"
                $FAR_CMD > /dev/null 2>&1
            fi
        else
            fi
        else
            if [[ "$state" == "far" && $rssi -ge $[$THRESHOLD+2] ]]; then
                msg "*** Device \"$name\" [$DEVICE] is within proximity"
                state="near"
                $NEAR_CMD > /dev/null 2>&1
                STARTX_PID=$(pgrep startx)
            fi
        fi
        msg "state = $state, RSSI = $rssi"
    fi

    sleep $CHECK_INTERVAL
done

[edit] perl script

I've got a link for you. It's an untested perl script. http://www.chaostal.de/members/balle/bluetooth/blue-cmd.txt

[edit] What about console locking ?

Nice work, but I need to lock and unlock a console for a server without X. To unlock it it-s simple: login with user and password, then verify if the Bluetooth device is in range. If it's not then logout, else drop to prompt. To lock run the script but instead of calling kscreensaver call logout. Simple as that.

Now since I'm not familiar with bash I'll need a little help:
1. Where should I call the script to check if my Bluetooth device is in range whan I login ? is it /etc/login.access ? Or is it ~/.bashrc
2. How do I split the bash file in two: one that searches and locks (as in logout) the console when the device is no longer in range and another that searches if the device in range when I login with name and password?
3 Is 'screen' a solution for not losing all the work done ? As in 'screen' when I first login, logout (and the work is still there), login and 'screen -r' back to my work.

Thanks.
PS: keep up the good work.

Fuzzy


Hi
I think pam_blue is what you are looking for. pam_blue
It's a pam module so even login gdm works automatically when my phone is near my computer.
-- ticapix

[edit] l2ping

I did pretty much the same thing with l2ping instead of hcitool. It seems to work slightly faster. (It takes hcitool rssi about 20 seconds to notice I'm gone.) --76.201.17.71 20:02, 17 July 2007 (UTC)


[edit] blueproximity

You can install blueproximity, that integrates with gnome, with an icon tray, and have a very easy and nice graphical appearance.

Personal tools