Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

We have an environment of a few thousand users running applications on about 40 clusters ranging in size from 20 compute nodes to 98,000 compute nodes. Users on these systems generate massive files (sometimes > 1PB) controlled by traditional unix permissions (ACLs usually aren't available or practical due to the specialized nature of the filesystem).

We currently have a program called "give", which is a suid-root program that allows a user to "give" a file to another user when group permissions are insufficient. So, a user would type something like the following to give a file to another user:

> give username-to-give-to filename-to-give ...

The receiving user can then use a command called "take" (part of the give program) to receive the file:

> take filename-to-receive

The permissions of the file are then effectively transferred over to the receiving user.

This program has been around for years and we'd like to revisit things from a security and functional point of view.

Our current plan of action is to remove the bit rot in our current implementation of "give" and package it up as an open source app before we redeploy it into production.

Does anyone have another method they use to transfer extremely large files between users when only traditional unix permissions are available?

share|improve this question
1  
Is there some reason why you can't just create a shared directory where all users have access? –  Zoredache Jun 18 '12 at 20:43
1  
If there's a directory with shared access, then users without permission would have access to files as they're being shared. In this environment, sometimes file-names are sensitive as well. So, unfortunately, a shared directory isn't an option. With a shared directory, there's also a possibility of a third user tampering with the file. –  Jon Bringhurst Jun 18 '12 at 22:12
    
Wouldn't be sufficient a cron job would would copy files itself? Example: user foo want to give file bar to user puppy. so he creates specialized directory which is scanned by cron job with a 'control' file containing receiving username. The cron jobs would read this 'control' file, if user is OK, destination directory has space is OK, the copy. You can still create a wrapper for 'give' to just create 'control' file to have historical compatibility. No need for suid-root, you can copy that file under non-root user and then sudo for changing ownership. –  Jiri Xichtkniha Jun 19 '12 at 15:25
    
If you just want to change permissions, chown should do it.. It seems you want to also copy the file, once both parties involved have agreed. –  zebediah49 Jun 19 '12 at 18:14
    
@JiriXichtkniha I do like the idea of a control file and a cron job. However, the files are too large to be copied. –  Jon Bringhurst Jun 20 '12 at 14:59
show 1 more comment

6 Answers

If the emitter is really willing to give the file away, you can use an SUID binary that moves the file to a directory that's writeable by all and has the sticky bit (like /tmp), then changes ownership to the new owner. chown(3) already takes care of removing the set-user-ID and set-group-ID bits for you. This way the new owner can do what he wants with the file, including moving it.

This directory writeable by all can belong to the user's home directory, in case you want to use multiple filesystems for home directories and want to make sure you don't cross filesystem boundaries as performance would immediately be terrible. In this case you'll probably want to make sure the recipient knows when a new file is offered.

E-mails would do the trick. A more Unixy solution would be a /etc/profile that lists your newly delivered files. Added bonus if you offer this feature with pam_echo (eg with file=/tmp/deliveries/%u, see pam_echo(8)). As with anything PAM-related, you'd want to check that all your implementations offer such a module first.

share|improve this answer
add comment

You could use a system with a shared directory, (possibly without execute perms.), where things for a given user are archived with a specific file name structure (to-$username_from-$username.tar, for example). Give makes the file and chowns it to the target user; take extracts the file and removes it.

If you want to do it as an actually move (IE, change file location and permissions; no copying because of the giant file size), you might be able to get away with moving to a shared directory with -x perms (so nobody can list files there), and the same chown method. mv, chown / mv.

share|improve this answer
add comment

As xryl669 says you can use a directory to actually share the files. It should look like this:

$ ls -ld shared
drwxrws--- 2 root usergroup 4096 somedate shared
$ ls -l shared
drwx-wx--- 2 user1 usergroup 4096 somedate user1
drwx-wx--- 2 user2 usergroup 4096 somedate user2
drwx-wx--- 2 user3 usergroup 4096 somedate user3
drwx-wx--- 2 user4 usergroup 4096 somedate user4

The give command becomes

#!/bin/sh
#Use a random suffix to prevent guessing
RANDOM=$(dd if=/dev/urandom count=4 2> /dev/null | sha512sum | cut -d' ' -f1)
NEWNAME=/path/to/shared/$2/$1$RANDOM
#Move the file
mv $1 $NEWNAME
#Make it readable
chmod 440 $NEWNAME

The take command looks something like this:

$ cd /path/to/shared/user
$ ls
...
$ mv somefile ~
share|improve this answer
add comment

I'd suggest to rewrite the app to indeed mimic a "give" and "take", but rather "push" and "pull" it from a protected directory. Your directory can be only accessible for the push/pull app - which handles the file moves. Alternatively, your app/script can create a random, temporary directory with permissions being set for the sender and receiver only.

Wish to have more security? You can PGP encrypt/sign the file (using the public key of the receiver).

In terms of redoing it from a "security and functional point of view", I'd strongly suggest not to create SUID programs. If you don't drop privileges in a proper way, you can virtually access any file on the system. If your program is buggy (buffer overflow, etc...) - one can exploit this to gain root access on your system.

share|improve this answer
add comment

This is probably no use to you but for reference cp --reflink source target does thin copies of files using copy-on-write.

This means you could copy the file outright and only changed blocks would actually be copied. Unlike a hard link the new file has its own inode and metadata meaning you can then provide the copy of the file to the new user using standard chown stuff.

As far as I am aware this is a feature that is only available on OCFS2 and btrfs currently. I guess that does solve your problem but seeing as the availability of it is not widespread it probably wont be useful.

share|improve this answer
add comment

I understand the need of "take" as "I can refuse to receive that file if I don't use that command". However it also means you need a side channel to send the file name.

If you want the top-notch system with all the bell and whistle, you might be interested in Ajaxplorer ( www.ajaxplorer.info ) which is a web based file explorer (with many credential plugins, like LDAP), where you have a "create public/private URL link" feature. A user would log in to your web server that's displaying her home folder, select a file, right click to "create private URL link" and set the email to send the link to. The other user will then have to click on the link in the email to download the file.

On an intranet, it'll be as fast as your webserver is able to be, and it's working correctly also on the public internet (but slower).

This also means your user don't need to have Unix command line knowledge.

(Disclaimer: I've helped in the development of this feature in AjaXplorer)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.