Skip to content

Commit

Permalink
[Serial] Open rfcomm device as unprivileged user
Browse files Browse the repository at this point in the history
...if he has read and write access.

This requires the watcher to wait if the device is busy which means it's opened by root (or any other user) and typically happens if ModemManager is present and probes the new device. The same method is used for PPPSupport now which previously always waited for five seconds unconditionally. While that is unnessary if ModemManager is not present, it seems to be too short if it is.
  • Loading branch information
cschramm committed Apr 16, 2017
1 parent 161b8a4 commit 7a33766
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 10 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ Makefile
/apps/blueman-sendto
/apps/blueman-services
/blueman/Constants.py
/blueman/plugins/mechanism/Rfcomm.py
/data/configs/blueman-applet.service
/data/configs/blueman-mechanism.service
/data/configs/org.blueman.Applet.service
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
* Bluez managers, Subclass from GDBusObjectManagerClient
* Notification: Use dbus for notifications and drop the libnotify dep
* Port NMPanSupport applet plugin to GDBus
* Open rfcomm device as unprivileged user if he has read and write access


### Bugs fixed

Expand All @@ -73,6 +75,7 @@
* Fix SerialManager plugin
* Close Notification when pair is successful
* Properly unregister NAP when unloading Networking plugin
* PPPSupport: Wait for ModemManager to complete probing and release the device


## 2.0
Expand Down
4 changes: 2 additions & 2 deletions apps/blueman-rfcomm-watcher.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ from gi.repository import GLib
import os
import argparse

from blueman.Functions import set_proc_title
from blueman.Functions import set_proc_title, open_rfcomm


def on_file_changed(monitor, file, other_file, event_type):
Expand All @@ -25,7 +25,7 @@ args = parser.parse_args()
mon = Gio.File.new_for_path(args.path).monitor_file(Gio.FileMonitorFlags.NONE)
mon.connect('changed', on_file_changed)

fd = os.open(args.path, os.O_RDONLY | os.O_NONBLOCK)
fd = open_rfcomm(args.path, os.O_RDONLY)

set_proc_title()
loop = GLib.MainLoop()
Expand Down
1 change: 1 addition & 0 deletions blueman/Constants.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ UI_PATH = "@pkgdatadir@/ui"
DHCP_CONFIG_FILE = "@dhconfig@"
POLKIT = "@have_polkit@" == "yes"
GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@"
RFCOMM_WATCHER_PATH = "@LIBEXECDIR@/blueman-rfcomm-watcher"

import os
import gettext
Expand Down
15 changes: 14 additions & 1 deletion blueman/Functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
from io import open
from time import sleep

from blueman.Constants import *

Expand All @@ -34,6 +35,7 @@
from gi.repository import GdkPixbuf
from gi.repository import GLib
from gi.repository import Gio
from gi.repository import GObject
import re
import os
import signal
Expand Down Expand Up @@ -398,4 +400,15 @@ def create_parser(parser=None, syslog=True, loglevel=True):
if syslog:
parser.add_argument("--syslog", dest="syslog", action="store_true")

return parser
return parser

def open_rfcomm(file, mode):
try:
return os.open(file, mode | os.O_EXCL | os.O_NONBLOCK | os.O_NOCTTY)
except OSError as err:
if err.errno == errno.EBUSY:
logging.warning('%s is busy, delaying 2 seconds' % file)
sleep(2)
return open_rfcomm(file, mode)
else:
raise
4 changes: 2 additions & 2 deletions blueman/main/PPPConnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from __future__ import division
from __future__ import absolute_import
from __future__ import unicode_literals
from io import open

import logging
from blueman.Functions import open_rfcomm
import tty
import termios
import os
Expand Down Expand Up @@ -123,7 +123,7 @@ def send_commands(self, i=0):

def Connect(self):

self.file = os.open(self.port, os.O_RDWR | os.O_EXCL | os.O_NONBLOCK | os.O_NOCTTY)
self.file = open_rfcomm(self.port, os.O_RDWR)

tty.setraw(self.file)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import subprocess
import signal
from blueman.Constants import RFCOMM_WATCHER_PATH
from blueman.plugins.MechanismPlugin import MechanismPlugin


Expand All @@ -16,7 +17,7 @@ class Rfcomm(MechanismPlugin):

@dbus.service.method('org.blueman.Mechanism', in_signature="d")
def open_rfcomm(self, port_id):
subprocess.Popen(['@LIBEXECDIR@/blueman-rfcomm-watcher', '/dev/rfcomm%d' % port_id])
subprocess.Popen([RFCOMM_WATCHER_PATH, '/dev/rfcomm%d' % port_id])

@dbus.service.method('org.blueman.Mechanism', in_signature="d")
def close_rfcomm(self, port_id):
Expand Down
18 changes: 16 additions & 2 deletions blueman/services/meta/SerialService.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
from __future__ import absolute_import
from __future__ import unicode_literals

import logging
import os
import subprocess
from time import sleep

from blueman.bluez.Adapter import Adapter
from _blueman import rfcomm_list, release_rfcomm_device, create_rfcomm_device
from blueman.Service import Service
from blueman.main.Mechanism import Mechanism
from blueman.Constants import RFCOMM_WATCHER_PATH


class SerialService(Service):
Expand All @@ -27,9 +33,17 @@ def connect(self, reply_handler=None, error_handler=None):
try:
# TODO: Channel?
port_id = create_rfcomm_device(Adapter(self.device["Adapter"])['Address'], self.device["Address"], 1)
Mechanism().open_rfcomm(str('(d)'), port_id)
filename = '/dev/rfcomm%d' % port_id
# We have to delay the access check to make sure the rfcomm system set up the permissions
sleep(0.1)
if os.access(filename, os.R_OK | os.W_OK):
logging.info('Starting rfcomm watcher as current user')
subprocess.Popen([RFCOMM_WATCHER_PATH, filename])
else:
logging.info('Starting rfcomm watcher as root')
Mechanism().open_rfcomm(str('(d)'), port_id)
if reply_handler:
reply_handler('/dev/rfcomm%d' % port_id)
reply_handler(filename)
except Exception as e:
if error_handler:
error_handler(e)
Expand Down
1 change: 0 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ blueman/plugins/Makefile
blueman/plugins/services/Makefile
blueman/plugins/applet/Makefile
blueman/plugins/mechanism/Makefile
blueman/plugins/mechanism/Rfcomm.py
blueman/plugins/manager/Makefile
blueman/main/Makefile
blueman/main/applet/Makefile
Expand Down

0 comments on commit 7a33766

Please sign in to comment.