For completeness, here's the simplest solution. I follow it with my view of why a versioning system is not appropriate.
I ended up enabling the setuid bit on the submission executable (chmod 4755), so that when students ran it, the program ran as me. All copying of files would then transfer ownership to me, and I could make the entire directory inaccessible to the students. This did involve a few hurdles in getting past Perl's added setuid security (untainting the input, untainting the PATH), but it worked out nicely in the end. The final script is around 20 lines.
The reason a versioning system is unacceptable is because this is a first course in programming. The students have never used a terminal, and are confused enough by the idea of ssh-ing into a server and transferring files back and forth. The details of a version control system are for upper-division classes (especially when a student is prone to terminal typos!). And you'd be surprised today how many of those courses do actually require one to learn a version control system (I took four courses that did in my undergraduate). A less significant reason I couldn't do a versioning system is that I couldn't have super-user privileges on the server, and wouldn't ask the professor to set up a versioning system just because I couldn't figure out the stupid setuid bit.
All I want for this course is a simple one-step submission to a private place. The problem was with my execution and lack of knowledge about unix permissions (not knowing about the setuid bit), not the structure of my solution. So Sean C.'s comment was the tip, but I didn't recognize it at first because it seemed like he meant the point was to run the script as root, and I didn't want that to protect the world from my own naivete about unix.
Here is the actual working script, and its permissions. Please point out any security holes you might see.
-rwsr-xr-x 1 260s12ta 260s12ta 600 2012-01-16 23:19 submit
#!/usr/bin/perl
use File::Copy;
$ENV{"PATH"} = "/usr/bin"; # appease the perl-suid security for shell calls
my $username = getlogin() or die "Couldn't access user login: $!\n";
my $dir = "/home/260s12ta/labs/$username/";
foreach (@ARGV) {
if ($_ =~ /([\w-]+\.tar\.gz)/) { # untaint the given filename
$filename = $1;
} else {
die "\nInvalid submission: $_ is not a .tar.gz file.\n";
}
print "Submitting $filename... ";
copy($filename, $dir) or print "Submission failed: $!\n";
chmod(0600, "$dir/$filename") or print "Submission failed: $!\n";
print "OK!\n";
}
/.../.../studentname
. then you can have an automated script that just clones/pulls their submissions wherever you want them to go. Since you are initiating the transaction, you don't have any permission issues, and of course, neither do they. Your script would presumably loop over the list of students, and could be totally automated, run as a cron job for example. – Faheem Mitha Jan 12 '12 at 19:26