Escalating privileges on linux programmatically - linux

I am creating a graphical installer that should run on Linux. Installing should consist of copying files to some places in /usr. Currently the installer is written in Python.
How can I escalate the privileges of my installer when I need to copy files? I looked at PolicyKit but
a) there doesn't seem to be a generic "install files" action-id for PolicyKit
b) of the action ids I can use, I don't think they are standard across distros
I also looked at PAM and I have code that uses libpam but I can't seem to do anything with it. After authenticating my user (by providing username and password) I don't have write access to /usr. I tried changing my user with os.setuid(0) after authentication but I get an error from the OS.
Also, strangely, it doesn't seem to matter what service I provide to pam_start. As long as the username and password are correct I can pass anything I want. I see I have /etc/pam.d/sudo. The below code is simplified, the password is correctly stored in a pam_conversation object and I do pass a handle object.
pam_start("my_user", "my_pass", "sudo_garbage_12345");
works just as well as
pam_start("my_user", "my_pass", "sudo");
That is, they both succeed.
As a last resort I can probably execute gksudo or kdesudo but I don't want to be tied to those programs. Requiring users to invoke my installer with sudo is a (very) last resort.

You might be better off wrapping RPM with a front end that takes the user options and invokes RPM to do the hard work. This also gives you infrastructure for managing dependencies and plays nicely with the existing package management system. If you need to run on a .deb based system (Debian or Ubuntu) you may also need to consturct a .deb and put some mechanism in the front end that works out which package management system is active.
Granting random users access to root privilege is generally viewed as bad form on Linux or Unix systems (or any multi-user system for that matter) as it is a significant security risk. However you do have the option of letting the user install it under their home directory (~/bin) if they don't have root access or sudo permissions that allow them to write to system areas. In this case you can require them to install it as root if they want to install in /usr/bin but permit them to install it under their home directory for their own use if they don't have root privileges.

For a graphical installer, stick with a graphical environment. Use gksudo or kdesudo if they are available, otherwise fail with an error dialog saying they need root. People (newbies in particular) will download your installer and double-click to launch it from their desktop, and you need a graphical way to ask them for their password. You don't want to pop open a terminal on them.
Given that, don't do sudo for them even if they are running from the terminal. Just output an error saying you need root and exit. If the user is already at the command prompt (like I most likely would be), I already know how to sudo or su myself into root if I want to do so. I promise you you will most likely ruffle some feathers if you attempt to make an experienced user root when they can do it themselves.
If you INSIST on doing a sudo yourself from within your installer, for God's sake please force a 'sudo -K' before you do to remove the previous timestamp. If you don't do this, and I have sudo'd recently, you will run your installer with me as root without my knowledge (since I don't expect that to happen). A 'sudo -K' will force a prompt that I can then decide whether I want to proceed as root or not.

The best way in this case is to use su within your program. Redirect inputs/outputs and you're good to go!

Related

VSCode - what exactly --user-data-dir is specifiying

What exactly is --user-data-dir specifiying?
From --help parameter:
--user-data-dir <dir> Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.
Is it storing some temporary files there?
Is it about the access path to config files?
I am asking as I want to run VSCode (or Codium to be more exact) with sudo (I want to edit system config file that is read restricted) which requires this parameter for reasons unclear to me.
Since sudo-ing VS Code at command-line launch is only a thing on Linux, this question assumes you're on Linux, and restricts its context to Linux.
TL;DR
To answer your question directly: the user-data-dir parameter points to a folder where all personalisation except extensions resides — unique to each user.
Why does sudo-ing Code need --user-data-dir?
In typical installations of either OS and VS Code, this folder owned by the regular user cannot be accessed by the superuser.
Hence a VS Code session running with effective UID=0 tries but fails to write to the invoking user's (not the superuser's) config folder. This is what the error message prevents from happening, by forcing the user to provide an explicit root-accessible folder.
Detailed Explanation
There are two main folders that VS Code uses to store configuration data:
An extensions folder (self explanatory) — contained in ~/.vscode[1]
user-data-dir; a folder for all other personalisable things (settings, keybindings, GitHub/MS account credential caches, themes, tasks.json, you name it)[2]
On Linux the latter is located in ~/.config/Code, and has file permissions mode 0700 (unreadable and unwritable by anybody other than the owner).
This causes issues, as VS Code tries and fails to access said directory. The logical solution is to either modify the permissions (recursively) of ~/.config/Code to allow root access, or — arguably saner and objectively more privacy-respecting — to use a separate directory altogether for the sudo'ed VS Code to access.
The latter strategy is what the community decided to adopt at large; this commit from 2016 started making it compulsory to pass an explicit --user-data-dir when sudo-ing VS Code on Linux.
Should You be Doing This in the First Place?
Probably not! If your goal is to modify system config files, then you could stick to an un-elevated instance of Code, which would prompt you to Save as Admin... when you try to save. See this answer on Ask Ubuntu on why you probably want to avoid elevating VS Code without reason (unless you understand the risks and/or have to), and this one on the same thread on what you could do instead.
However, if the concerned file is read-restricted to root as well, as in the O.P’s case, then you hardly have a choice 😕; sudo away! 😀
[1] & [2]: If you want to know more about the above two folder paths on different OSes, see [1] and [2]
Hope this was helpful!
It might be helpful to easily find the default location of the user-data-dir on any OS. It can be found with this command:
Developer: Open User Data Folder
workbench.action.openUserDataFolder
which is in the Insiders Build v1.75 now, Stable soon. Opens your OS file explorer app to the location.

User-friendly execution of downloaded file in Linux

On my website I need to give users an ability to download and easily start my executable (AppImage binary) on Linux.
For Windows version it is just .exe which works after downloading and clicking:
Download file
Click on file in browser downloads panel to start it
For Linux user now needs to do following:
Download file
Open folder containing file from browser downloads panel
Right click on it to add exec permission
Click on "Allow execution of this file" checkbox
Press Ok
Click on file to start it
It is hard to explain this flow for regular user, it makes users leave away.
Is it possible to minimize it to minimal clicks as on Windows?
Any advises appreciated to achieve minimal clicks. I can compile app for any format (its on electron but I can process it before upload)
I thought about using .deb . It will limit app for Debian-based only, but main problem in same time that I did not find ability to run post installation to exec app, and I don't want ask user to enter start menu.
Executable bits are a basic UNIX security measure thus it is not really easy to work around this (for good reason). Thinking about this, for the specific case of downloaded files, Windows also applies some restrictions (special NTFS stream which tells Windows Explorer to warn about the dangers of an executable file from the Internet).
You can of course provide your application as a .tar.something archive and store executable files in there. After extraction, they will normally have the correct execution bits set.
The option with the deb-package can also solve your problem (for some users) but is a little more complicated:
User downloads deb package
User clicks on deb package and has some program installed that provides a GUI for installing packages (like gdebi). Like on Windows there will be some "security check" in form of a dialog box where the user needs to enter a (sudo) password. Afterwards, apt will install the package
If the package is created correctly, it can transport the executable bit correctly such that no explicit permission change is needed afterwards. If for some reason there is need to do something post-installation, Debian packages can provide postinst scripts which run (as root!) at the end of the package's installation.
In any case, as dealing with executable files is a common procedure on Linux, it might not scare so many users away as expected. If you want to make it comfortable for the users, provide the package as they expect/like them. On Windows I would think that to be a .msi package and on Linux I prefer a package corresponding to my distribution (.deb, .rpm).
If you want the users to update their packages regularly (good for security) then it is helpful to provide a "repository" that users can add and install your package from. Of course, "the best" is having a package as part of the distribution, but that is quite some effort and needs to pass a lot of "quality assurance gates" :)

Run Linux GUI (X) application as another (system, non-root) user

i am trying to write a custom (GUI) program installer which needs to run as a specific (system) user (without a home directory) - let's call him "installer". Things i have tried or pondered to achieve this in a couple of different ways:
launching the GUI installer app as user "installer" through (gk)su(do) (-u). the problem is that a. these commands are not available on every
distribution or do not behave the same everywhere thanks to internal aliases, and b. the x server does not allow me to connect as a different user without some potentially insecure "xhost +" modification (the old "cannot connect to X server :0.0" problem).
avoiding the X server for the installer routine and create a separate (CLI) binary for the chmod/file copy process, while the GUI runs in current user mode. the problem is that i have to give the password to the (sudo -S) command in clear text, which shows up in the logs, so not a good idea either.
several command combinations of export display, .Xauthority, xhost and anything i could find on stackoverflow, without much success.
so, what do i actually need?
a distro-independent, secure way of launching a GUI application as another (non-root, but "/home"-less system) user
an elegant way of asking the current user for the password of user "installer"
a solution that does not require the current user to enter the root password first, or install the application as root.
i'd be thankful for any thoughts on the matter.
[edit] to clarify, i do not rally want to install new programs into the established linux file structure. The whole setup is this:
I have a main program that will be installed by the root. this program can be extended by modules.
these modules will be installed into a custom folder (let's call it "/progmodules") which is owned by the "installer" user. the goal is to have authorized users to be able to install new modules, without giving them full root access.
any users who want to install new modules should be able to run the installer GUI app, enter the "installer" user password, and then have the files transferred.

What permissions should 'texlive' have?

For years I have been using MacTeX which installs in /usr/local/texlive, and have recently started using Homebrew to manage some packages (though not — yet — TeX). As a consequence of the adoption of Homebrew, I've changed the owner of all of /usr/local to Me:admin (from root:wheel).
Is this change of ownership safe? Is there a reason that texlive needs to be owned by root?
Normally usr/local is owned by root:wheel so that multiple usr's can access it, so by default everything installed to it is owned by root:wheel. Homebrew takes the rather unusual (but convenient) step of subverting this. It says, look this computer is just being used by one user, so I'll give her control of usr/local. It does this to
Make it more likely that all unixy installs will work for you
Make it safer (if there are any other users using the computer) - as a homebrew user, you'll only screw your own account up wiht homebrew if something goes wrong.
As you installed tex before homebrew it has root:wheel ownership, this has nothing to do with texlive, and everything to do with the normal usage of usr/local. If you change its permissions to Me::admin, then only you will be able to use texlive - I'd just leave it alone :)

How can I offer options to save data to a user from an rpm?

I deliver an application via an RPM.
What I need to do is if the user uninstalls the application (rpm -e) to get a chance to do a back up of some the files that are part of the application installed.
Additionally on (post) installation I want the user to get a chance to replace some of the installation's files with the ones that he saved during a previous uninstall.
To do this I thought to make an interactive RPM.
But it did not work. Googling I found that some of the commands e.g. read are ignored in an RPM spec somehow and additionally the idea to get interactive input
from a user is frowned upon and not recommended.
My question is, am I really following a wrong approach here? Should I be doing it differently? How? I can't think of another solution on this specific problem.
Any help?
Interaction with the user while un/installing RPM is not a good practice. The philosophy behind it is that RPMs should able to be un/installed automatically, for example, when installed via YUM. If you must, you have several options:
Best: Create a script that get all information from the user, and write it to a file. In the RPM prerequisites, verify that the file exists.
Optional: Embed the RPM within a bash script that interacts with the user, extracts the RPM and run it. I believe Java RPM does it to let you accept the EULA.
Not a good idea: I have read somewhere that RPM reads from /dev/tty so you can try to add exec 0</dev/tty in the beginning of the %pre or %post

Resources