How can I allow regular user to chown a file

I want to allow a regular user (group of admins) to chown a file that they own to another user. By default only root can do this. I know I can get around this with SUID and SUDO, but I want to be more restrictive than just letting the users run the chown command as root on any file.  

I would like to write a script that first verifies that the user owns the file and that the user is not going to change the owner to certain owners (e.g root).  So rather than open up unlimited chown access, I want to only run the command as root after checking some things in the script. Any way to do this?
Who is Participating?
There's two reasonable solutions to this.

One is to use ACL's, which can be used to grant per-user read permission for the file; since the admin can create the file in the user's home directory, the admin can also grant that user - and only that user - permission to read the file.  The ACL grants the permission, even though the group/other permissions don't imply it.

The second is a tightly controlled script or compiled program, that takes very specific input, and runs setuid root.  The action would be to supply a filename (or content on stdin), and a target username, and allow the script only to be run by your staff group.  The script would likely use a special drop-directory, or prefix the filename, and check that the destination file does not already exist.

I'm not fond of the second approach in the least, and I'd strongly recommend ACL's for this; this is literally the purpose of them.  ACL's are used commonly in Windows environments, but Linux users tend to shy away from them, largely because they're not frequently discussed.  They're secure, useful, and appropriate for this scenario.

Other solutions would be methods such as using a web server script that has its own authentication layer, an FTP server that limits to a drop-directory, or using sudo to allow your staff group to run commands as the recipient users to make a copy of the file (temporary race condition, while the file exists and is available to anyone),  using a blind drop-file directory and a pre-arranged filename (removing the read bit from the directory, so you can't do an 'ls' on it), or e-mail'ing it to the user with a procmail script that creates the file.  Most of these have some security risks, either a brief window in which the file can be detected, or potential for abuse (e.g. forged e-mail for the procmail recipe).

The simplest "hack" solution, that may be available, is for each user to have their own group (gid), and add your staff members to all the user's groups, so they can chgrp the file to the user's group.  Some distributions, such as Red Hat, create a unique gid by default, simplifying this approach.

But really, ACL's are the way to go, here.  If the `chacl` command is in /usr/bin/, you most likely have everything you need to use it, other than some "recipes" for your staff.
You are running into a two part issue. Changing ownership of a file that is in your directory is of little use if the person does not have rights to access the directory.

What is it you are trying to achive?  You could make the users members of the same group and then set access rights on the shared directory where the files are stored to match the access you want.

peiaspAuthor Commented:
The issue is this. The admin user needs to create a file for another user to read in their home directories. The admins have privs to write files to the directory based on their group. But they cannot give the user the ability to read the file unless they set the "other" permissions. So, I would like to allow the admin user to set the file they created to be owned by the user that needs to read it. Essentially one regular user giving away a file to another regular user. If I use SUID or SUDO, the first regular user can change the file to be owned by anyone including root, which I want to disallow, so I do not what to give full access to the chown command as root. My desire as to leave the chown command as it is, but run it as root from inside of a script that the admin user can run, but not alter. That way I can control what the chown command does.
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

An admin user would normally have access to chown.
Setting the umask of 022 rather then 077 on the admin user would set default permissions on a created file to 644 which would allow a user read access.

An alternative if local users rely in part on in hereting their settings from a /etc/profile is to setup a directive there to copy files designated for the user
i.e. cp /var/somesharedlocation/$USERNAME/* /home/$USERNAME/
All the admin needs to do is to create a file in the location for which ever user. The user will have the file on their next login owned by them.

Setting the directories of /var/somesharedlocation/$USERNAME with a Group ID might be an option you might consider.
What you are looking for is a wrapper, the problem you are overlooking is individuals not changing ownership from usera to root, but changing important files from root to usera.
i.e. a user mistakenly run chownscript / usera groupa.
Do you want to implement all the checks to minimize alterations to the file system, commands, etc.??
Could access control lists (acl) help?

There are a lot of good sources of information on using ACL's, I've only ever used them in the RHCE exam myself.
If you use ACL's you will need to make sure that the acl information is backed up, some tools do not do this by default.
peiaspAuthor Commented:
You are correct, I don't what the user to change any file owner unless they already own the file in question. That would be controlled in the script.  What I really need is a way to allow user "A" to change ownership of a file to be owned by user "B", without giving user "A" unlimited access to chown as root. If there is a way to do a run as root inside of a shell script, I can handle all the other checking. I just need to be able to have user "A" execute a script (that user "A" is allowed to run, but not read). From that script, I will check everything. User "A" owns the file, user "A" is only changing ownership to the user "B" that he should be changing to, etc. But then I need a way to invoke the command chown as root without opening the chown command up to user "A" for all situations.  So, really all I am asking for is a way to do is to run the chown command as root from within a script that is launched by a non-root user.
If all the control you mention is in the script then what is wrong with running the script as root.

As you say, the script would check that the user is the owner of the file, it would be simple to check if the user/owner was root and abort as required.

Just out of interest, what are you trying to achieve, would group permissions do? I understand that you want userA to change their own files to userB etc but I'm still not sure of the overall goal.
what about an suid perl script?  normally I hate suid scripts as they are a security risk, but in this case I dont see a way around it.

an suid perl script can keep track of the userid that launced the program, and then after it elevates its own privs to root it can check the user that the chown is going to and if that validation step works, then as "root" the perl script can execute the chown

boils down to writing your own replacement for chown maybe something called perl-chown and then have your admin users execute that instead of chown directly.

if you think this idea will work, I can give you some pointers on how to write suid perl scripts safely.

reason I suggested it is that we have a custom app that runs as userx but usery needs the output files generated by that custom app.

I wrote a suid perl script that becomes root goes into the userx home dir looking for the file that is needed, and if found does what needs to be done with it.

your idea is the exact opposite of my problem, but the answer should work just as well.
I'm not really prepared to refute the ACL approach becuase from a techical side its correct, but here is the issue:

ACLs on linux are "relatively" new, introduced in the 2.4 kernel series and not fully matured till some time after they were introduced, and I'm not sure when all the tools became stable enough to trust in a production environment.  From this perspective its a little like SELINUX, a great idea, but still a new player, and some of the apps I run "still" dont like SELINUX because the app was written before SELINUX came to be.

I'm not ready for ACLs and SELINUX simply because some apps dont work well with them, and because of this I had to shy away from learning the skill since I couldnt apply it.

The trick here is not specifically to use the "best" tool as it may not work where you need it to work, especially if you dont understand how it works.  Sometimes the "best" tool is the one you understand the most, and have worked with in the past and know how to make happen what you want to happen.

Otherwise you have to decide if the extra learning curve time is worth it, depending on the timeline of your project.

Based on what Ive read on ACLs they are the perfect tool for what you want, but there may be other factors that prevent you from implementing ACLs just for this project.  I dont know if you are using ACLs elsewhere, and if you are, maybe all you have to do is add the right ACL.

but if you don't use ACLs, as I don't, then you have the added problem of trying to figure out how to use ACLs in general, in addition to how to use ACLs to solve this particular problem.

Only you can decided which is appropriate for you.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.