I'm writing an application using C on Linux. In my application, I need to do some tasks at the beginning with normal user (Non root user) while I need to do some tasks with root user in the middle of execution as well.
By the way, I cannot modify configurations of normal user. So I cannot add normal user to sudoers. I cannot modify any OS configurations as well.
What my application really do is execute applications, get their outputs for analysing.
Some applications need to be run with root. I use multi-threads to execute and analyse outputs of these applications in parallel then stores report of each application in a singleton called Report. I call these applications using execvp in sub-process.
The main purpose of my application is to automate software testing. And most task is required to run in software owner which shall not be root.
So, the problem is
how can I switch user during execution?
Is there anyway that I can implement this within 1 executable?
Do this with POSIX APIs is better.
Run my application with normal user, provide root password to my application, switch to root using root password.
Read more about setuid executables and setreuid(2) and execve(2) syscalls. Be careful, you'll need to put the setuid flag on the executable with chmod u+s (see chmod(1)) after changing its ownership (with chown(1)) and code carefully to avoid security holes.
(so I recommend to have your code reviewed by someone knowing the setuid mechanism and aware of security issues)
Setuid is the basic mechanism (used by su, sudo, super, login etc...) programs to get (or revoke) privileges. See credentials(7) & capabilities(7).
It could be safer to start some helper process (as root, or start some setuid executable perhaps in /usr/libexec/ ...) and communicate with it using some inter-process communication facilities (like pipe(7)...). For example, it is not recommended to use GUI toolkits like GTK or Qt in root processes. If your app has some GUI, it is reasonable to run its GUI in a non-root (ordinary user) process and run as root the (hopefully small) helper process doing the real job requiring special privileges.
Before coding, I recommend reading a good book like Advanced Linux Programming and syscalls(2) and the documentation of every system call you would use. Security aspects are especially important.
Setuid executables don't necessarily require or use any password; it is the other way round: programs requiring passwords (notably login, su, sudo etc....) are setuid (and they are free software on Linux so you can study their source code); try ls -l /bin/su /usr/bin/sudo /bin/login to check that.
Since you want to emulate various user environments, be aware of environ(7).
Related
I have to develop C API to shutdown linux system using reboot function through UI APPLICATION instead of system call and exec function.This reboot linksays that in order to run this function caller must have the CAP_SYS_BOOT inside its user namespace.
Right now this function only work with root user I have to modified it to make it use for normal user too.How to set sufficient privilege inside C function using capabilities in order to shutdown linux system by any user?
turnoff()
{
sync();
reboot(RB_POWER_OFF);
}
Your process had to have that capability; you can't grant it to yourself at runtime (which would defeat the whole purpose of capabilities).
Read about capabilities(7).
Use setcap to set the capabilities of an executable file. This is typically done at installation time. As root:
setcap cap_sys_boot+ep /path/to/your/executable
Capabilities can also be inherited by child processes.
I need to implement an small capability system for Linux similar to Plan 9 cap device. Host owner (root in Linux) allows user1 to impersonate user2 writing user1#user2#random-string to /dev/caphash. Any user1 process that knows random-string can change its uid to user2 writing user1#user2#random-string to /dev/capuse.
On Linux, any privileged process can impersonate any unprivileged user with setuid(2) system call, but I do not know any mechanism to allow horizontal impersonation. How do Linux do it?
Serge E. Hallyn submitted p9auth to the Linux-kernel mailing list in April 2010, which would have provided pretty much this functionality (albeit in the last submitted form, with a slightly different interface). Unfortunately, it was not included in the Linux kernel.
The underlying security paradigm in Linux is vertical, rather than horizontal.
Privileges are separated into capabilities, and they can be acquired at exec time only. Extra privileges can be dropped at any time. In practice, you use filesystem capabilities and the setcap utility to give an unprivileged binary some specific capabilities whenever it is executed, regardless of the identity of the user executing it. (With Linux kernels 2.6.33 and later, it is no longer possible for any process to modify the capabilities of another running process.)
The key point to notice is that in Linux, only a privileged process (a process with the CAP_SETUID) can change its identity at run time.
In other words, point of exec is used in Linux for elevation of privileges, with the now-privileged binary changing to the specified user (and/or group and perhaps supplementary groups), dropping extra privileges. I am not aware of any mechanism that would allow an unprivileged process to change its credentials without an exec.
For the OP, this means that the Plan 9 interface (/dev/caphash, /dev/capuse) will not work. A comparable Linux interface implemented in userspace will require the exec of a binary as part of the change in credentials, but other than that, I don't know enough of OP's use cases to make any suggestion.
In-kernel, such an interface is obviously possible (as shown by the first link in this answer), just not available in the vanilla kernels.
In linux (and in unix in general) there's a similar feature that has to do with one of the bit permissions of an executable file. If you have an executable binary file, marked as setuid bit, then when you execute that file, the kernel runs that executable by setting the effective user id of the process to the owner of that file. So the mechanism works if you have execute permissions to execute that file. Let's suppose you want users a, b and c to impersonate user d on execution of some program. You first create a group of users (group setuid_d) in the system and put on it all the users a, b and c. then you create the executable, make it belong to user d, and group setuid_d. Once this has been done, as user d or as root make the file executable only by the group setuid_d and activate the set uid bit in the permissions
$ chgrp setuid_d program
$ chown d program
$ chmod ug+x,o-x,u+s program
$ program # you'll be effectively user d when executing program
Is it possible to use a set of C library or system calls to drop all user privileges on POSIX, or at least on Linux? Note that I am not asking how to drop root privileges, which is what all of the other StackOverflow search results seem to be asking and answering.
I want the same effect as switching to user nobody, but stronger if possible. That is, I want my C application to do the following:
Run as a normal user, not root, and without the setuid file permission bit
Retain the ability to access specific files and open outgoing network connections
Voluntarily and permanently lose the ability to read and write files in specified (or all) directories, especially $HOME
If possible, give up or sandbox all other nonessential abilities, like opening a listening socket with accept
Things I have considered so far that don't fit the bill:
Switching to user nobody with setuid/setgid
Ordinary users are forbidden from switching to other users (like nobody), and the application should not require root just to switch to nobody.
Linux/POSIX.1e Capabilities
Capabilities only add root-like privileges, not take away ordinary user privileges
Traditional seccomp
My application will need more than just exit, sigreturn, read, and write
Things that look interesting, but for which I couldn't find documentation, appear to be unmaintained, or appear to be non-portable:
seccomp-bpf
AppArmor
grsecurity RBAC/role-based access control
So is there a well-documented, preferably portable way to drop nonessential user privileges and sandbox a process without having to become root first?
It's unlikely any solution will work on all POSIX, since POSIX doesn't define the mechanism you're looking for.
Looking at just the requirements and just Linux, probably the easiest way to satisfy them is actual via the security modules. Any of apparmor, selinux, RBAC will do what you need, but only via external profile - not something built into your app. The problem may be that adding a profile in all those cases requires the root user to do it (but the profile applies to user process too).
A bit more complicated solution that almost satisfies the requirements is seccomp. While it doesn't understand paths at all (you can only see pointers), there are ways to limit the access: seccomp policies can be defined per thread, so you could redesign your system to have a "path verification thread", which doesn't do anything apart from reading paths and returning sockets if they match your specification. Then limit that thread to just recv(), open() and send(). Thread doing other work can then drop open() and use the other service.
Or if you can configure the paths at program startup, you can put them into an array, mark that page as read-only, and setup seccomp policy which will only accept open() with filenames from that array (that's just a pointer comparison in that case).
To some extent, the approach of splitting application into separate processes which have very limited responsibilities is something you could replicate on other systems, but without the same guarantees as on Linux. For example qmail is kind of a system of very small processes which work as a pipeline for data (simplification). On Linux you could still apply seccomp to them, on Solaris just drop exec and other capabilities, on other systems... I don't know, but probably you can do something.
I have a written a C program that creates a file "abcd.txt" and write some data into it. I was executing my code by logging with a username"bobby" and so the file abcd.txt was created with owner as bobby.
But my task is, even though I execute my code with some username "bobby", the file should always be created with owner as root. Can someone help me by saying how this could possible?
As a general principle you need your effective uid (euid to be root) either when you are are writing the file or when you perform a chown(2) on the file.
If you are doing this under Linux then there are linux specific methods that you can use.
Generic Solution
Without availability of sudo
This is the old UNIX DAC approach, it's fraught with peril. It assumes that you do not have something like sudo installed or cannot install it.
Your executable should be owned by root and have the executables setuid bit set.
Process
You should use seteuid () to drop your privileges from root to bobby for most of the operation, including writing. When you are done, bring your privilege level back up to root using seteuid(0) and perform a chown() (or fchown on the fd) on the file to change its ownership to root.
some basic safety
For safety set it up so that your executable is owned by root:safegrp where 'safegrp' is name of a group unique to users who are allowed to execute this file (add bobby to safegrp) ; and ensure that the setuid executable's mode is 4510 ;
With availability of sudo
If sudo is available on your system then follow the same process as above for dealing with privileges within the executable but DO NOT set the file mode to setuid, have safegrp added to sudoers for this executable and now bobby can run it with sudo /your/bin/prog
Linux specific solution
POSIX.1e
It is possible to have tighter control over the file use POSIX.1e capabilities support. In your case you wish to grant SYS_CHOWN to your program;
For security reasons, I would probably set that up as a COMPLETELY separate binary or a sub process and still use sudo and perform appropriate dropping of privileges.
linuxacl[ACL Using Access Control Lists on Linux] has excellent tutorial on this topic
SE-Linux
You can use Mandatory Access Control to limit the access to such a dangerous binary but SE linux is a pain to configure :^) although a possibly a good approach
You probably don't want to run your program as root, unless you really have to. Perhaps run "chown" from a shell script after running your program? Or, you can use chown(2) from a program running as root (or with equivalent capabilities, on linux).
Use the chown() method. There are probably more authoritative links, but this one is nice since it includes the calls to getpwnam(). I've done all of this in the past, but unfortunately I don't still have the code (it's owned by IBM).
http://manpages.courier-mta.org/htmlman2/chown.2.html
I have written a cgi-bin application in C that runs in a browser and allows the user to open an interactive shell and view & edit files on a Linux machine. It runs as the standard apache "www-data" user. I just added a login screen to it where the user types in their name and password (in a form) but I cannot authenticate the user using getspnam since this function only works when running as root.
What options do I have to check the login credentials of a user when not running as root?
PS: In my interactive shell I can type "su root" and then type in my password and it does elevate to root fine so it obviously can be done interactively.
I think you want to take a look at Pluggable authentication modules. AFAIK, PAM handles all the messy stuff for you and you just need to do a few function calls to authenticate the user on whatever the backend to authenticate users on the Linux host is (be it shadow passwords, nis, ldap, whatever)
Here's a short guide about integrating your C code with them.
With regard to your PS: Well, when you do a su root you're switching to the root user. So yes, of course, root can read the shadow file, you all ready said that.
With regard to your problem: Can't you have your apache processes temporarily elevate to root (by calling setuid or similar) to perform the authentication?
Good luck!
As suggested, I think PAM is the modern way to do this. But if you want to go old school, you need to create a setuid-root program (not a script) to do your authentication.
There are lots of gotchas with setuid-root programs, which is why PAM is likely better.
Here's a link to some good papers on safely writing setuid-root programs.