UID/GID change notification - c

My application creates a rudimentary ACL and communicates this to a Kernel Module. The ACL contains a list of UID/GID. The checks on these IDs are custom and on top of what the system already provides.
Now if the root/user changes UID/GID the ACL needs to be refreshed. Is there a way to get notification in an application whenever UID/GID changes e.g. through usermod command? Right now the platform is Linux but we could be porting this to other platforms as well(AIX/Solaris)

I'd say there is no way to reliably detect a change in the UID/Username mapping, especially when you go cross-platform. The user database may reside in NIS, NIS+, or nowadays, LDAP. They might be integrating their UNIX/Linux systems with a Windows Server running Active Directory, or they might be using something more obscure like Hesoid. I know of no way to receive any automatic feedback from these various databases. But also, any good book on UNIX Administration will tell you to not change these mappings, or at the very least, if you must, don't ever re-use a UID. Don't forget, the filesystem whether it's using standard POSIX permissions or POSIX ACLs will also be storing UIDs that won't be getting updates if an Administrator decides to change the UID for a user. The Kernel and filesystem both treat a specific UID as a specific user, regardless of their username. I really don't think you need to bother with the case of an Administrator changing UIDs for a user, it's likely to be too error prone for everyone.
Also, a quick look at NTFS on Windows will reveal that it also stores the equivalent of a UID called SID, it'a a long number used to represent a user and Windows does not provide or expect you to be changing the mapping of that SID to a specific Username. The SID is what the NT Kernel uses internally, not a username. If I open up the Security tab on a file, for a split second I may see numbers until Windows is able to query the Active Directory Controller and give convenient usernames to those numbers. Ultimately, it's the SID, not username that uniquely identifies the user.

On Linux, inotify does what you want. On other systems, try FAM.

One possible way (triggered from Frédéric's reply) is that I could possibly set a inotify/(dnotify gasp! for older kernels) operation on /etc/passwd because that file will always change for at least any change in local user privileges. Trouble is how to do this in NIS environment.

In the typical Unix security model, you should only care about the numerical value for GID/UID, not the mapping between human-readable string and numeric value. As that seems to be the case, have you carefully considered what you are trying to accomplish? Maybe it would be better to pass the name or a name/id tuple, instead of just the id?

Related

How do I input a password from a makefile or system( ) call?

I'm working on a C project that makes connections to remote servers. Commonly, this involves using some small terminal macros I've added to my makefile to scp an executable to that remote server. While convenient, the only part of this I've not been able to readily streamline is the part where I need to enter the password.
Additionally, in my code, I'm already using system() calls to accomplish some minor terminal commands (like sort). I'd ALSO like to be able to enter a password if necessary here. For instance, if I wanted to build a string in my code to scp a local file to my remote server, it'd be really nice to have my code pull (and use) a password from somewhere so it can actually access that server.
Does anyone a little more experienced with Make know a way to build passwords into a makefile and/or a system() call in C? Bonus points if I can do it without any third-party software/libraries. I'm trying to keep this as self-contained as possible.
Edit: In reading responses, it's looking like the best strategy is to establish a preexisting ssh key relationship with the server to avoid the login process via something more secure. More work up front for less work in the future, by the sound of it, with additional security.
Thanks for the suggestions, all.
The solution is to not use a password. SSH, and thus SCP, has, among many many others, public key authentication, which is described all over the internet. Use that.
Generally, the problem you're trying to solve is called secret management, and the takeaway is that your authentication tokens (passwords, public keys, API keys…) should not be owned by your application software, but by something instructing the authenticating layer. In other words, the way forward really is that you enable SSH to connect on its own without you entering a password by choosing something that happens to not be an interactive authentication method. So, using a password here is less elegant than just using the generally favorable method of using a public key to authenticate with your server.
Passing passwords as command line option is generally a bad idea – that leaks these passwords into things like process listings, potentially log entries and so on. Don't do it.
Running ssh-keygen to create the keys. Then, adding/appending the local system's (e.g) .ssh/id_rsa.pub file to the remote's .ssh/authorized_keys file is the best way to go.
But, I had remote systems to access without passwords but the file was not installed on the remote (needing ssh-keygen to be run on the remote). Or, the remote .ssh/authorized_keys files did not have the public key from my local system in it.
I wanted a one-time automated/unattended script to add it. A chicken-and-the-egg problem.
I found sshpass
It will work like ssh and provide the password (similar to what expect does).
I installed it once on the local system.
Using this, the script would:
run ssh-keygen on the remote [if necessary]
Append the local .ssh/id_rsa.pub public key file to the remote's .ssh/authorized_keys
Copy back the remote's .ssh/id_rsa.pub file to the local system's .ssh/authorized_keys file [if desired]
Then, ssh etc. worked without any passwords.
UPDATE:
ssh_copy_id is your fried, too.
I had forgotten about that. But, when I was doing this, I had more complex requirements.
The aforementioned script would merge/combine all the public keys and update all the authorized_keys files on all the systems. This would be repeated anytime any new system was added to the mix.
you never need to run ssh-keygen on a remote host, especially not to generate an authorized_keys file. –
Marcus Müller
I think that was inferred but not implied as a requirement [particularly in context]. I hope the answer wasn't -1 for that.
Note that (1) ssh-keygen is needed for (3) copy back the public key.
Ironically, one of the tutorial pages for ssh-copy-id says run ssh-keygen first ...
It's been my exerience when setting up certain types of systems/clusters (e.g. a development host/PC and several remote/target/test ones), if one wants to do local-to-remote actions, invariably one wants to do:
remote-to-local actions -- (e.g.) I'm ssh'ed into a remote system and want to do rcp back to the development system.
The remote system needs to do a git clone/pull from [and, sometimes, git push to] the local git server.
remote-to-remote -- copying/streaming data between target systems.
This requires that each system have a private/public key pair and all systems have an authorized_keys file that has the public keys of all the other systems.
When I've not set up the systems that way it usually comes back to haunt me [usually late at night when I'm tired]. So, I just [axiomatically] set it up that way at the outset.
One of the reasons that I developed the script in the first place. Also, since we didn't want to have to maintain a fork of a given system/distro installer for production systems, we would:
Use the stock/standard distro installer CD/USB
Use the script to add the extra/custom config, S/W, drivers, etc.

How do I drop supplementary groups in Linux?

I have an executable that's ug+s to a non-root user and group. I would like it to leave all the supplementary groups it originally had behind. Is there a way to make this happen? It doesn't look like the setgroups call allows you to do this if you're not root. And when I try it, I get EPERM.
It seems like there ought to be a way to lose privileges you previously possessed.
The short answer is "A process without CAP_SETGID can't.". And it is by design that setgroups can't be used to remove groups when the process has no privileges. The previous link is to an excellent LWN article detailing why not.
In my particular case, since I'm immediately creating a user namespace, those supplementary groups get mapped to 'nobody' anyway. And so it isn't very important. If it is important, you can use setcap(8) to set capabilities on a wrapper executable that checks that it's being run by the expected user with the expected group permissions and then drops the groups and drops CAP_SETGID and runs the executable you really want to run. The command you would use to do this is:
sudo setcap cap_setgid+ep wrapper_exe
Be careful though, it's now possible that someone who has a shell on your system can use that executable to run some sort of privilege escalation attack if you did not write it very carefully.

Drop privileges as regular non-root user for sandboxing?

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.

Modify file permissions using C API

I have a server component that reads its configuration from a file. The configuration file is also read and written by an administration component. The components are separate programs, and they will be running under separate accounts. I want to change the ACL on the configuration file to:
application: read
administration: read and write
Its important to drop write from the application because the application opens a listening socket. That is, its high risk and I want to contain it as much as possible.
After some searching, it looks like ioctl is used to do it in C. ioctl_list offers a list of control codes but its not apparent to me how to add two users with different permissions on the configuration file. The man page online at die.net does not discuss the permissions in-depth or offer sample code. For example the word "perm" (root of "permission") only shows up once in the discussion.
On Windows, reducing permission to honor least privilege is drawn out but its pretty straight forward (Richter gives good examples in his Advanced Windows programming series).
How does one change permissions on a linux file using C APIs? What control codes are to be used?
Thanks in advance.
This is not done with ioctl, but rather with dedicated system calls: chmod, chown, and chgrp for the basic user/group/other set of file permissions, and acl_* for full-fledged ACLs. You probably also want to know about the setuid, setgid, and setgroups system calls, which are how you drop privileges in a running application.
You can accomplish your goals using only the basic user/group/other permissions. Configure your system as follows:
The server application has a dedicated user ID and group; let's say they are both named nlserver ("nl" for "noloader").
The administrative component also has a dedicated user ID and group, let's say nladmin.
The configuration file is set to be mode 0640 (aka -rw-r-----) and owned by user nladmin, group nlserver. (The code responsible for doing this should be in the administrative component, not the server itself.)
When the server starts up, after doing everything it needs to do as root (e.g. bind low-numbered ports), it uses setgroups, setgid, and setuid (IN THAT ORDER!) to change to user nlserver, group nlserver, and clear the supplementary groups list. Only after doing so does it open the configuration file.

C Privilege Escalation (With Password)

I need to write a C program that will allow me to read/write files that are owned by root. However, I can only run the code under another user. I have the root password, but there are no "sudo" or "su" commands on the system, so I have no way of accessing the root account (there are practically no shell commands whatsoever, actually). I don't know a whole lot about UNIX permissions, so I don't know whether or not it is actually possible to do this without exploiting the system in some way or running a program owned by root itself (with +s or whatever). Any advice?
Thanks!
P.S. No, this isn't anything malicious, this is on an iPhone.
Under the UNIX permissions system, you need to run a file owned by root itself that's marked setuid-root (+s, as you said) or communicate with some process that is already running as root.
If there is no such file, you are out of luck.
You can do this with setting suid bit to application, but if you want from this c application run a some shell this was be runned on local user if you do it normally this is security system.
However you can read/write/execute files owned by root, but if your user is not in group of file your target file must have setted read/write/execute on last 3 bits or when your user is in file owner group you must check/apply this to 3 bits in middle position. (3 first bits setting permission to owner but this may not by a usable information for you).
If you dont have any access to root account. Then if group and other user permissions dont access functions as you must have, you can't do with this anything except trying get some prilveaged user for access this file. In other cases you can do some fixes in file access permissions but not from this system, you must get hard drive from this device and attach to other to change it or load on this device some live system to change this. However you can do this on privleaged system not on this.
More information about SUID bits you can find at:
http://www.codecoffee.com/tipsforlinux/articles/028.html
http://www.everyjoe.com/newlinuxuser/explain-what-is-setuid-and-setgid/
The iPhone SDK doesn't allow this. Your application is sandboxed and it is not allowed to go outside of that sandbox except in very specific ways provided by Apple. The only way to do this on an iPhone is to jailbreak it.

Resources