What user account are you using on the gateway? leaprun can only be used from within accounts that privleapd is configured to allow. The user and sysmaint accounts in Whonix are automatically allowed, but for other accounts, you can add them to the privleap group and reboot to allow them. privleapd will then automatically allow access from those user accounts when the account logs in.
(If you need privleap access from accounts that don’t ever truly log in, you can use a persistent user for that. See man privleap.conf.d, search for persistent-users.)
In the past, Tor Control Panel (TCP) had been run as root with gksudo/lxsudo or alike.
As running GUI applications as root was always frowned upon, allegedly impossible on Wayland (actually not true but off-topic), TCP had been ported to Polkit, where the GUI runs as non-root but actions requiring root (write to Tor configuration location) are allowed. Suitable is available in most Linux distributions.
As we’ve worked through Strong Linux User Account Isolation, Polkit was no longer suitable (?) or for completeness sake we ported every action requiring higher privileges from Polkit to privleap, which as far as I know so far is only used by Kicksecure, Whonix, as TCP wasn’t maintained for any other Linux distributions anyhow.
A longer term security improvement goal is to run Polkit in sysmaint session only. Not in user session.
If you like to support other Linux distributions without dependency on privleap, then polkit support needs to be brought back (from git history). If available, use privleap. If unavailable, try polkit, if available. Preferably, keep the privleap dependency since it’s well maintained, stable and simpler.
The problem was that the cloned gateway I’m using was not updated properly. It had been reverted to “PERSISTENT mode” without the option to use “unrestricted” as should be in Whonix templates.
Hence the “ERROR; could not connect to privleapd!”
tor-control-panel and sdwdate-gui packages were moved in whonix-gateway-18. They work as expected, after purging older ACW ang TCP.
ACW code is is much shorter and readable. The changes mentioned earlier (retrieve Tor settings, request new Tor circuits, plus some others) are implemented.
Still struggling with Disable network in TCP (does not set “DisableNetwork 1” when calling set-disabled in tor_status. ACW does it). But there is an improvement, because it was crashing the application in the previous version.
Could you review, especially if my minimally modified version of sdwdate-gui does not clash with your latest version.
tor-control-panel was pushed as “dummy commit” by lack of imagination, or the description would have been too long
I think it’s possible to merge it, along with my one line modified sdwdate-gui. For the moment, my whonix-gateways keep asking to be updated with the separate TCP and ACW packages, which are no longer working. I cannot afford to review them. The merging would make future work easier. I know that sdwdate-gui keeps getting updated, but hopefully not for now in the running version in whonix-gateway-18 . Otherwise, I’m afraid that it will be up to you to fix it.
I’ve started reviewing the combined app. It might take a while (there’s a lot of code to go through and the changes are large enough that it’s not easy to pick out everything that changed with a diff), but so far it’s looking decent. Thanks for your work on this
I’m trying to chase the references to helper-scripts in tor-control-panel. Found one so far in tor_status.py. There is a way around, tested successfully.
Any other use of helper-scripts, to your knowledge?
No, but Search the Source Code can catch this. And no worries, this will also be done during code review. Now that there’s a renamed “api function”, it’s clear that Search the Source Code will be necessary.
polkit itself in no longer available in Debian. pkexec is still alive, though. I might be a solution (to be reviewed first, I need more understanding of the internals) if we want to make TCP working in plain Debian. Perhaps another option would be to give passwordless privilege in /etc/sudoers.d to the few commands requiring sudo
Whichever the choice, I have been devising a way to minimize the changes in TCP code. I have added a commands.py module with two dictionaries with the same keys, one for whonix, currently used in TCP (makes the code more readable in my opinion), one for Debian with empty values.
EDIT.
Since, I believe I have reached a dead end in Debian. Torbrowser runs on its own, without the Tor package. Tried many workarounds with no luck. It means that the tor commands used in TCP (stop, reload, restart…) have no effect at all. Was thinking of installing tb-updater, but it’s a no go, user-wise.
I think you mean PolicyKit, which was renamed to Polkit. Polkit itself is used to allow a massive amount of functionality to work (including USB drive mounting, shutdown without requiring root, it’s used by systemd, etc.). I don’t think it’s gone. pkexec relies on Polkit to work.
FYI, I finished the review I mentioned a few days ago and made some notes (left as comments in the code itself). See:
The tl;dr: is that there are several issues that may be release blockers, and several other minor issues that could used fixed to make future maintenance easier. I think it might be better to work on getting the code into a releasable state before working on new features or efficiency improvements. I’m happy to help with that, or leave it to you to look at if you’d prefer.
I prefer to try it myself, for the sake of learning. A remark: there are still many references to acw.do-something in TCP, while the package will hopefully be tor-control-panel with ACW as a child application. This is valid in sdwdate-gui too.
Since it was written, I have pushed the version with
The main ones I think need fixed before merge are:
QSizePolicy arguments to QGridLayout.addWidget() (in anon_connection_wizard.py, look for the commend TODO: QGridLayout isn't supposed to take QSizePolicy arguments, how does this work?)
Use of open(...).read() to read the entire contents of a file (this shows up in a few places)
Yahoo still listed as an email provider usable for getting bridges from BridgesDB (TODO: Yahoo is no longer an acceptable email provider for this. https://blog.torproject.org/new-release-bridgedb-071/)
no_controller popping up a window but callers expecting it to return a string (TODO: Callers expect this to return a string, not pop up a window! This is therefore broken.)
Double-check that the restarting of Tor after sending a Signal.NEWNYM is safe (TODO: Do we know that Tor has fully processed the NEWNYM signal at this point?)
Beyond that, some that would be nice to fix before merge but aren’t essential:
Lack of IPv6 compatibility (TODO: socket.gethostbyname() only supports IPv4. Whonix now supports IPv6. Can this be changed to use socket.getaddrinfo() instead?)
Parser issues in torrc_gen.py. (This one would be a release blocker IMO if the code wasn’t already released, but this existed prior to your refactoring work so I don’t think it counts as a blocker.)
The rest are mostly robustness concerns and cosmetic things, it would be nice if they were fixed but if the code works otherwise, they can wait.
I did not find QSizePolicy directly used by a QGridLayout. I guess you refer to lines 215 and 218in anon_connection_wizard.py. The arguments (sizepolicy, alignment) are passed in addWiget, which is perfectly acceptable. I could have set them beforehand; let’s say it saves two lines of code. I can add those lines and simply call QGridLayout.addWidget(widget) if you think it makes the code more readable.
I removed Yahoo and the duplicate code in info.py custom-bridges_help.
self.custom_frame = QFrame()
self.custom_frame.setMinimumSize(425, 520)
self.custom_layout = QGridLayout(self.custom_frame)
## TODO: More unnecessary parenting of widgets.
self.custom_label = QLabel(self.custom_frame)
self.custom_label.setMinimumHeight(24)
self.custom_bridges_help = QPushButton(self.custom_frame)
self.custom_bridges_help.setMinimumSize(120, 24)
self.h_spacer = QSpacerItem(40, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.custom_bridges = QtWidgets.QTextEdit(self.custom_frame)
self.custom_bridges = QTextEdit(self.custom_frame)
self.custom_bridges.setMinimumSize(440, 480)
## TODO: QGridLayout isn't supposed to take QSizePolicy arguments, how does this work?
self.custom_layout.addWidget(self.custom_label, 1, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.custom_layout.addWidget(self.custom_bridges_help, 1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding,
Qt.AlignmentFlag.AlignRight)
Specifically the last four lines. This is in anon_connection_wizard.py. self.custom_layout is a QGridLayout, and QGridLayout Class | Qt Widgets 5.15.19 does not document QSizePolicy arguments being accepted in QGridLayout’s constructor. My best guess is these are probably int variables under the hood, in which case they may get re-interpreted as rowSpan and columnSpan arguments.
Whatever the type of layout, in the statement layout.addwiget(widget, args) , the arguments, even if QSizePolicy if not mentioned in the docs, apply to the widget, not the layout.
Not true. Tried on another widget (line 200), it does not accept it.
So for the sake of clarity, it was changed to setting qsizepolicy before adding the widget to the layout.