Closed The-Compiler closed 3 years ago
Ah, that's unfortunate. I'm in the wheel group, which apparently allows me to run Networkmanager commands as $USER.
$ ./networkmanager_dmenu
Traceback (most recent call last):
File "./networkmanager_dmenu", line 859, in <module>
run()
File "./networkmanager_dmenu", line 855, in run
sel()
File "./networkmanager_dmenu", line 284, in __call__
self.func(*self.args)
File "./networkmanager_dmenu", line 593, in toggle_bluetooth
with open('/dev/rfkill', 'r+b', buffering=0) as f:
PermissionError: [Errno 13] Permission denied: '/dev/rfkill'
Any idea how best to fix and document this? Maybe only show the option when a user has permission?
I'm in the rfkill
group, which allows me to write to /dev/rfkill
as $USER :wink:
$ ls -l /dev/rfkill
crw-rw-r-- root rfkill 0 B Sun Sep 13 11:17:38 2020 /dev/rfkill
But yeah, I suppose that should be documented at least - only showing the option when the user has permission seems like a little bit much magic, but I'm not sure.
This article shows a polkit snippet for rfkill permissions through dbus. I don't have conman installed yet I can still disable bluetooth through blueman. Would it be possible to somehow use that to enable the rfkill permissions as an additional alternative? Do all distros have an rfkill group? I don't have an Ubuntu desktop available, but my Ubuntu server doesn't have that group.
As I'm looking, I actually don't know what is giving me permission on my Arch desktop to turn Bluetooth on and off through the blueman applet!
Hmm, good point, blueman did work before I added myself to the rfkill
group!
It looks like the Archlinux blueman
package comes with a /usr/share/polkit-1/rules.d/blueman.rules
:
/* Allow users in wheel group to use blueman feature requiring root without authentication */
polkit.addRule(function(action, subject) {
if ((action.id == "org.blueman.network.setup" ||
action.id == "org.blueman.dhcp.client" ||
action.id == "org.blueman.rfkill.setstate" ||
action.id == "org.blueman.pppd.pppconnect") &&
subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});
and the blueman rfkill code does:
self.confirm_authorization(caller, "org.blueman.rfkill.setstate")
with confirm_authorization being defined here: https://github.com/blueman-project/blueman/blob/b4f0738d5a9a360e6f8fef0e2a0bc9d4f9b38383/blueman/main/MechanismApplication.py#L86-L101
It looks like that's not some kind of permission elevation though, just an additional "voluntary" permissions check - what actually makes it work is that /usr/lib/blueman/blueman-mechanism
is running as root... Probably via /usr/lib/systemd/system/blueman-mechanism.service
somehow? Then again I never started it by hand, this is a bit concerning if I'm honest!
(edit: Ah, I guess via /usr/share/dbus-1/system-services/org.blueman.Mechanism.service
which starts that systemd service... Still, lots of crazy stuff going on there!)
However, I hope we agree we don't want this kind of complexity in networkmanager-dmenu
:sweat_smile:
I now added a notification when this happens:
I've had to change notify
a bit so I can pass a detailed text as well as the urgency - IMHO it makes sense to use "critical" for error messages (the Desktop Notifications Specification says "Critical notifications should not automatically expire, as they are things that the user will most likely want to know about. They should only be closed when the user dismisses them, for example, by clicking on the notification.").
I've also pushed a commit to change all error messages to critical urgency - if you'd prefer this in a separate PR or not at all, please let me know and I'll revert that commit.
Looks good! Thanks for the input. I like the critical notifications for errors.
I use NetworkManager for Bluetooth tethering with Android - for some reason, NetworkManager itself doesn't provide any way to disable/enable Bluetooth radios, even though it can connect to them just fine, if they are enabled.
Thus, I always need to first use rfkill or blueman to enable Bluetooth before I can connect with networkmanager_dmenu. With this change, I can do it all right from rofi.
Admittedly, this is a bit of a hack. I first thought I'd use the commandline output of the
rfkill
tool first, but its output seems to have changed a bit between differentutil-linux
versions. It does offer JSON output since utils-linux v2.31.1 (December 2017) which does seem to be part of Debian Buster (the current stable) and Ubuntu 18.04 LTS, but not e.g. Ubuntu 16.04 LTS which is still supported until 2021.Thus, I decided to use the kernel interfaces directly, which is a bit more stable and avoids having to spawn a subprocess which essentially does the same in C anyways.
I'm not aware of a way to do the same thing in a more high-level way (e.g. via Networkmanager/DBus), so that's what I ended up with looking at the Blueman code. Blueman does actually use DBus if ConnMan is available, but since that'd probably conflict with NetworkManager I doubt anyone using
networkmanager_dmenu
will have it running.