I am creating a utility which will run on Linux machines. For the purposes of this discussion, let's say its analogous to make.
Here's the deal : sometimes, when you run the utility, it creates files in the directory you're running in, and these need to be created as the same user/group as the user executing the tool. This is the "make main.o" scenario - create main.o from main.c. This will be the default when you run the utility as your own user, which is fine.
Sometimes, when you run the utility, it creates files in /usr/local/bin and such, which need to be root:root. This is the "sudo make install" scenario - create /usr/local/bin/executable under root:root. This will be the default when you run the utility as root, which is fine.
The problem is, that in all cases, the utility needs to manage some additional cache files, say in /var/cache/utility. When you run the utility as root, these files are root:root, which is a problem the next time you run the utility as your normal user. They can't be deleted/modified.
What I am wondering is, is it a good idea to create a dedicated user/group for this utility when you install it? I know apache, svn, and others do this. This is the only approach I can think of, but I am open to other solutions.
If I DO have a dedicated user/group for the utility, how do I temporarily assume the identity of that user for the purposes of managing the cache files, and then resume the previous identity for the remainder of execution (for creating regular files as user:user, and system files as root:root) ?
What I've got so far is something like this:
- getpwnam(predefined_utility_user_name) // get the uid
// do stuff in /var/cache/utility
- seteuid(getuid()) // resume previous id
- setegid(getgid()) // resume previous group
THE PROBLEM : assuming the predefined_identity does NOT work when running the utility as yourself! It works when you run as root (obviously).
I am fine adding myself and other users to the group associated with the utility. However, that does not work. So - how do I make that work? Is this a bad idea?
EDIT : Response to below suggestion
I've done some more reading and I think I have a good solution using #2 you've suggested it looks like this
The executable of the utility is owned by utility:utility and has both u+s and g+s permissions. Therefore, right when I start executing, I have euid/egid of utility, and utility, respectively. I have ruid/rgid of whichever user executed the program. So, what I can do is, when I start executing, setegid(getgid()) and seteuid(getuid()). This allows the process to assume the identity of whoever executed the program. I will maintain this for the entire duration of the program, EXCEPT while dealing with /var/cache/utility, I use the same technique to assume the utility:utility identity.
I don't need to partition the software, there is no group to which your user must belong, the executable just needs its own user/group and u+s and g+s. I guess you have to trust that the program is not malicious, but you have to assume that anyway if you're going to execute it. Thoughts?