How do I grant root access to a user application? - c++

I have a user-level C++ test application running on a linux mobile device. One of the test involves enabling/disabling printer paper sensor which requires root privileges writing on a device file. Is there a way to grant my application that kind of privilege? If none, is there a workaround for that?

This will do,
as root execute:
chown -v root:root /path/to/yourapp
chmod -v 4755 /path/to/yourapp
or alternatively
chmod -v u+s /path/to/yourapp
or alternatively
man chmod
This will not work with scripts. And yes, you should take seriously what jdizzle said about dropping unnecessary privileges.
Another way to solve this is to make the user who runs the application a member of the group that owns the device file. For example,
ls -la /dev/devicefile
crw-rw---- 1 root printer 4, 0 may 6 10:56 /dev/devicefile
members of the printer group can read and write to the device, so you just need to add joe to the printer group (and restart the session).
gpasswd -a joe printer
If you need to adjust the devicefile permissions, you probably will need to edit udev rules to make it permanent. But chmod should work too.
Other options worth investigating: setcap(8) (nice guide here) and sudo(8).

You can set the program setuid root, which means it will always run as root even when run by a user. This typically requires special care to drop privileges inside the program once the necessary actions requiring root access are completed.

You could also have a helper program, itself setuid root -or with appropriate capabilities, or started thru sudo- which communicate with the printer. Your main application would fork & exec that program and communicate with it thru pipes, so it should not be itself running as root.
The helper program would be a simple executable (with appropriate capabilities) which would only be started by your main application (not directly by the user) and communicate with it thru pipes or program arguments, etc.
A lot of graphical administrative programs are done likewise: the graphical part is a program separated from the administrative part, and they communicate appropriately. Only the administrative program (usually existing command line programs like adduser) need special privilege.

you should definitey try to avoid running your program as "root", as this would not only allow your program to read/write /dev/sensordevice but it would grant access to virtually everything on your system (including the ability to completely brick it)
you should therefore try to add fine-grained access to just the ressource you need, using proper groups and making sure that your device-file grants your group write access.
see (e.g.) udev on how to write a proper udev rule, that grants write access for a certain device to a given group.

Related

calling mount() system call as a non-root user

I am writing a C/C++ program that needs to be able to mount a disk as an ordinary user (can't run with sudo). Typically, questions of this type pertain to using the mount command in a shell, and the answer is to use the "user" option in the /etc/fstab entry corresponding to the disk in question. However, I don't think that the listings in the /etc/fstab matter at all when using the mount system call in a program.
However, since it is clear that the mount command is capable of allowing non-root users to mount disks (assuming the /etc/fstab is setup right), and presumably the mount command calls the mount system call, then I think it should be possible to achieve what I want.
How can I successfully call the mount() system call without running the program with sudo?
A valid solution to this dilemma is to pack the mount/umount calls into a shell script, provide sudo permissions for that to the application user, and call it from the application e. g. using system(). Make sure that the script does adequate error handling and perhaps logging, returning the appropriate exit code on error or success you can handle in the calling application.
/etc/sudoers.d/myApplication:
<appUser> <host> = (root) NOPASSWD: /usr/local/bin/myMountScript.sh
In your application:
const int result = system("sudo /usr/local/bin/myMountScript.sh <options>");
//Error handling on result follows below
Another possibility is to use capabilities, as mentioned in a comment above, and set them on the binary, but that's bit more complex, so I don't get into details here.

Proper method to acquire root access on Linux for Qt applications

Good day
Background:
I am creating an OpenVPN wrapper application for Linux systems which is near completion. I have run into a little snag.
OpenVPN requires root access to modify routing tables (add and remove routes). Here is where things get a little vague and confusing.
Hopefully, by extending this question, some industry standard answers and solutions could be shared.
Documentation:
So, after a number of hours searching, I compiled a list of possible methods for acquiring root access, however none seem to be official nor any real solid guidance given to acquire this SU privilege.
Let us consider the following methods.
1. Using pkexec & polkits
Please find official freedesktop polkit documentation here and here for some information on best practises
There are a few tutorials found online using pkexec and polkits
- here, this helped me create my polkit file.
- SO Thread
- And a lovely small tutorial for Qt applications
To give a brief explanation (of my understanding) about pkexec and polkits:
polkits:
polkits consist of actions and rules (see documenation for indepth reading and explaination). It defines actions of an application and the rules associated with it. Rules can be defined as a user belonging to a specific group, whereby the action queries the rule, it it has succeeded in passing the rule, the user is authenticated automatically (with no popup password prompt), else they are required to enter an administrator password
pkexec:
a application used to interface with the polkit actions and authenticate an application to acquire root access.
These require adding an action into /usr/share/polkit-1/actions/ and /usr/share/polkit-1/rules.d/ (amongst other directories, see documentation for all locations)
This method seems to be well used (but requires a bit more explaination to be understood easily, imo)
note: There are qt-polkit libraries made available for usage, see their github repository
For a simple TL;DR version, see this
The polkit file I created (note this may not be correct, but it does work for me):
Location where it can be found/added (there are others too)
/usr/share/polkit-1/actions
Policy Kit file name:
com.myappname.something.policy // the .policy is required
Note:
com.myappname.something
is refereed to as the namespace of the policy (reading the documenation, this will not be clear)
Policy Kit content
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
<policyconfig>
<vendor>My App Name</vendor>
<vendor_url>http://myappurl.com/</vendor_url>
<action id="com.myappname.something.myaction-name">
<description>Run the polkit for My App which requires it for X usage</description>
<message>My App requires access to X, which requires root authentication, please let me have su access</message>
<icon_name>myappname</icon_name>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/myappname</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>
Notes about my policy file (the important bits)
This is just an example, see documentation for official examples and descriptions:
<vendor>My App Name</vendor> is the application name, it can have spaces
<action id="com.myappname.something.myaction-name"> any action name here.
NOTE!
The file name -> com.myappname.something.policy and,
the action id -> com.myappname.something.myaction-name should have the same namespace
The icon name should be in accordance with with the latest freedesktop icon spec found here
TL;DR (or don't want to):
icon locations are:
1. /home/yourusername/.icons (sometimes not there)
2. /home/yourusername/.local/share/icons
2. /usr/share/icons
as long as they conform to the sizes and are a .png, you can pass the filename only (omitting the format)
Very Important:
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/myappname</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
When calling pkexec <myappname>, and NOT having these lines (honestly, I am not quite sure purpose of them), one will run into an error similar to this:
2017-12-19 12::58:24 Fatal: QXcbConnection: Could not connect to display ((null):0, (null))
Aborted (core dumped)
Note: keep the key the same, however you can and probably should change the exec.path key to your application location.
How do policy kits work?
In short, if you review the lovely example mentioned earlier (and skip all the very similar names of files), it becomes clear.
When one runs:
pkexec <myappname>
this calls the local authentication agent to run the application (in our case) as root.
This is handled by the actions (the policy kit mentioned above). Further more, the rules utilize the action id to perform addition queries, etc which can be viewed in the provided examples above.
Once the admin password has been entered, depending on the 'settings' entered into defaults (see here), we have:
auth_admin_keep
Like auth_admin but the authorization is kept for a brief period (e.g. five minutes).
Thus, the user can (in my OpenVPN application) connect to an OpenVPN connection for the next 5 minutes, until the password is requested again.
2. Sudo (/etc/sudoers):
This seems to be the go to method for most users who required root access, however it is not recommended:
e.g. Check root access before running the main application by calling a singleShot QProcess with arguments:
/bin/sh -c sudo -v
will result in exit code of 1 in various Linux distributions (thus causing me to search for alternatives)
3. setuid():
A very good example can be found here, unfortunatly it doesn't seem to work on modern Linux distros for the reason of it being a security hole which can easily be exploited.
In short, the process requires one to:
chmod +x <executable>
and checking that the s bit is set in the application using getuid() to get the user id and getgid() to get the group id of the user.
These functions can be found in Linux headers defined by:
<sys/types.h> // defines structs
<unistd.h> // defines methods
However, this does not seem to work with modern day Linux systems. Here is the output of executing a root owned application with the s bit set, run as a normal (unprivileged) user:
2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid, this is a security hole. ((null):0, (null))
Aborted (core dumped)
Farewell, setuid()
4. Other methods:
PAM
for further reading, see
man page
tutorial/explanation
A QT Forum question regarding cross platform PAM intergration
QT usermode
Qt provides a small implementation for acquiring root access, but it is only available to Linux distrobutions using yum package manager.
A question followed up on this, see this QT Forum question
Problem:
Above may only include a small portion of available methods to acquire root access, however considering that some applications are used globally, they are often attacked or pried apart or even compromised.
After doing this research, it has broadened my knowledge, but hasn't given me a sure-fire method which is recommended, but only hints.
Question:
Which method above is preferred in industry i.e. when should I use the one over the other (PAM vs polkits vs simple sudo) and if other methods are available, are these preferred?
However, this does not seem to work with modern day Linux systems.
Here is the output of executing a root owned application with the s
bit set, run as a normal (unprivileged) user:
2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid, this is a security hole. ((null):0, (null))
The above error has nothing to do with modern day Linux systems. Its a Qt protection against stupid developers using setuid without understanding it.
Simply call
QCoreApplication::setSetuidAllowed(true)
when your application starts, and then you can do setuid() just fine. You can even run privileged commands before dropping down to 'normal' user.
Summary:
Your Qt application must have root owner, and setuid bit set. Example debmaker is my Qt application that I want to perform privileged actions from. So after I build debmaker, I do:
sudo chown root:root debmaker
sudo chmod 4755 debmaker
(The latter sets the setuid bit)
Now run the Qt application
./debmaker
First thing the app does is check geteuid()==0 and getuid()==1000 (1000 is my user id, 0 is the root)
Then it launches a new process (using QProcess in Qt). This will run in privileged mode. (Example my child process is called chroot)
Now drop the main application (my debmaker) to normal user level by calling
setuid(getuid());
chroot (the child process ) will keep running as root user.
The main application, now no longer is running in elevated mode, but can send requests to its child process which is still running in elevated mode.
QProcess *chroot = new QProcess;
blah blah setup the chroot and start it
chroot->write("chown root:root /home/oosman/foo");
The last line will send a message to the child process. You read the stdin in the child process, parse the command, check it to ensure its not malicious (or malicious depending on your intent!) and execute the command.
Good research. But want add new case:
I think better way is make new Unix group and grant write access to target config file for group members. You will just add users to group. And only that users will change routes.
If routes defines with particular program. You can allow to run that program only for group members.

Start/Stop daemon on Linux via C++ code

I am trying to find out a way to launch a custom daemon from my program. The daemon itself is implemented using double-forking mechanism and works fine if launched directly.
So far I have come across various ways to start a daemon:
Create an init script and install it to init.d directory.
Launch the program using start-stop-daemon command.
Create .desktop file and place in one of the autostart paths.
While the 1st 2 methods are known to start the service using command line, the 3rd method is for autostarting the service (or any other application) at user login.
So far my guess is that the program can be executed directly using exec() family of functions, or the 'start-stop-daemon' command can be executed via system() function.
Is there a better way to start/stop service?
Generally startups are done from shell scripts that would call your C++ program which would then do its double fork. Note that it should also close unneeded file descriptors, use setsid() and possibly setpgid/setpgrp (I can't remember if these apply to Linux too), possibly chdir("/"), etc. There are a number of fairly normal things to do which are described in the Stevens book - for more info see http://software.clapper.org/daemonize/daemonize.html
If the daemon is supposed to run with root or other system user account, then the system /etc/init/ or /etc/init.d/ mechanisms are appropriate places to have scripts to stop|start|status|etc your daemon.
If the deamon is supposed to be for the user, and run under his/her account, you have a couple of options.
1) the .desktop file - I'm not personally a fan, but if it also does something for you on logging out (like let you trigger shutting down your daemon), it might be viable.
2) For console logins, the ~/.bash_login and ~/.bash_logout - you can have these run commands supported by your daemon's wrapper to start it and (later) shut it down. The latter can be done by saving the PID in a file or having the .bash_login keep it in a variable the .bash_logout will use later. This may involve some tweaking to make sure the two scripts get run, once each, by the outermost login shell only (normal .bashrc stuff stays in the .bashrc, and .bash_login would need to read it in for the login shell before starting the daemon, so the PATH and so on would be set up by then).
3) For graphic environments, you'd need to find the wrapper script from which things like your X window manager are run. I'm using lightdm, and at some point /etc/X11/Xsession.d/40x11-common_xsessionrc ends up running my ~/.xsessionrc which gives me a hook to startup anything I want (I have it run my ~/.xinitrc which runs my window manager and everything), as well as the place to shot everything down later. The lack of standardization for giving control to the user makes finding the hook pretty annoying, since just using a different login manager (e.g. lightdm versus gdb) can change where the hook is.
4) A completely different approach is to just have the user's crontab start up the daemon. Run "man 5 crontab" and look for the special #reboot option to have tasks run at boot. I haven't used it myself - there's a chance it's root restricted, but it's easy to test and you need only contemplate having your daemon exist gracefully (and quickly) at system shutdown when the system sends it a SIGTERM signal (see /etc/init.d/sendsigs for details).
Hope something from that helps.

Are system() calls evil?

I am designing an C++ app that, among other things, executes a few scripts every now and then. The app should be efficient and preferably platform independent.
The issue is, however: is there a reason one shouldn't use system() call for launching scripts and use, for example, POSIX facilities instead? The discussion on the matter that I've seen so far usually boils down to:
system() is less flexible. (Fine with me)
It offers no control of the command being executed. (Fine with me, I just need a return value from the script)
It is not quite platform independent. (Now, this would be a concern. I would really love to see an example where it behaves differently on different platforms)
It is a security concern. (Again, this would be an issue. Can someone provide an example of a potential security problem with system()? )
Any other issues?
3) It is not quite platform independent (Now, this would be a concern. I would really love to see an example where it behaves differently on different platforms)
Well, for instance system("ls") would probably fail in Windows, since there is no ls command.
4) It is a security concern. (Again, this would be an issue. Can someone provide an example of a potential security problem with system() ? )
If the argument passed to system comes from user input, and not properly validated, it can be used to execute unwanted things with the privilege levels of the original executer. If its static content, its quite easy to find that within an executable image and modify it to do nasty things as well.
(3) If you just want a counterexample, for example grep behaves differently on Solaris vs Linux vs whatever.
(4) Your program's privileges are inherited by its spawned programs. If your application ever runs as a privileged user, all someone has to do is put their own program with the name of the thing you shell out too, and then can execute arbitrary code (this implies you should never run a program that uses system as root or setuid root).
(5) It will probably be saner to maintain in the long run to use the posix facilities because you won't have to rely on a specific set of external scripts or binaries already existing wherever your program runs.
I maintain a system that consists of several separate executables. In this case I have control over the permissions, names, calling conventions, security over all supported platforms. In this case, system() works just fine. The applications communicate through a RDBMS.
Again, as others have noted "The Devil's in the details".
Regarding security concerns, a classical example about (4) is the following scenario: imagine the user is prompted to give some directory name to be backed up into a std::string dirname; then you'll compute some backup directory name into a std::string backup and do
system((std::string{"cp -a "} + dirname + " " + backup).c_str())
Now think what happens if a malicious user enter foo bar; rm -rf $HOME; ls as the dirname and backup is /vol/backup_2015_fev/. The system command would execute
cp -a foo bar; rm -rf $HOME; ls /vol/backup_2015_fev/
which is not what you expected (all the user's $HOME would be deleted!). This is an example of code injection, and when using system you should ensure that it never happens (e.g. by sanitizing and/or escaping every user input related string)
Also, the PATH might not be what you believe it is (e.g. starting with /tmp/ and a malicious user having done ln -s /bin/rm /tmp/cp before your system runs).
I used the system() call in my CGI C++ app under windows and Linux too.
One problem I had was when using system() was not having the proper access rights to execute my skript with the web user.
I did not have that problem any more when using the CreateProcess() method.
Whatever command you want to execute just store that in a file c.txt. Pass that file to the execl() like as done below.
fd = open("c.txt", O_CREAT | O_RDWR, 00777);
write(fd,arr,sizeof(arr));
if(fork() == 0)
{
execl("/bin/sh", "sh", "-c","sh c.txt", (char *) 0);
}

A method to change effective user id of a running program?

I'm writing a simple package manager and I'd like to automatically try sudo if the program isn't run as root. I found a function called seteuid, which looks likes it's exactly what I need, but I don't have the permissions to run it. So far all I can think of is a bash script to check before they get to the actual binary, but I'd like to do this all as C++ if possible.
Is there any method of changing a processes's euid after it starts executing? Or a way to call sudo?
Here's how these functions work.
If a program has the setuid bit, it will execute as it's owner. Once it is executing, it can call seteuid to run as the original user instead of its owner. Ditty for setgid.
The principle is the principal of least privilege. If I write a program that needs special access, I want as little code as possible to run with the access. So, I install it setuid, but the first thing it does it give back the privileges until the narrow window of code that needs them.
You can't call sudo (except, of course, via fork/exec). You can be a program like sudo that is installed setuid and which decided when to use that awesome power appropriately.
As bmargulies says in his answer, you can do this if you binary is owned by root and has the setuid bit set - but then you will need to implement the authentication part (checking that the user is actually allowed to become root) yourself too.
You'd be essentially rewriting sudo within your application - the best way to handle this is to do what you suggested yourself, and install your application with a wrapper script that uses /usr/bin/id to check if it is root, and if not, call out to sudo (or su).