Commit 42e84c26 authored by Leigh Stoller's avatar Leigh Stoller

Add a setuid utility script that will chown a directory tree

(recursively) to the UID of the real user (not effective) user. The
user must have write permission on the enclosing directory.

Currently, this script is is called from the Archive code, when
copying in files, to avoid permission errors when the current user is
not the same as the previous user.

This script can also be used from several other places that have
exhibited similar directory permission problems.
parent 93b40622
......@@ -40,6 +40,7 @@ my $ELABINELAB = @ELABINELAB@;
my $MD5 = "/sbin/md5";
my $MKDIR = "/bin/mkdir";
my $CHMOD = "/bin/chmod";
my $SUCHOWN = "$TB/sbin/suchown";
my $CHGRP = "/usr/bin/chgrp";
my $TAR = "/usr/bin/tar";
my $RSYNC = "/usr/local/bin/rsync";
......@@ -405,6 +406,15 @@ sub ArchiveAdd($$;$$$)
}
my $repodir = "$directory/repo";
my $checkin = "$directory/checkins/$view";
#
# If the target rootdir exists and is not writable by the current
# user, then run a chown over the whole subdir. This will avoid
# avoid permission problems later during the rsync/tar ops below.
#
if (-e "$checkin/$rootdir" && ! -o "$checkin/$rootdir") {
mysystem("$SUCHOWN $checkin/$rootdir") == 0 or return -1
}
#
# Copy the file in. We use tar on individual files (to retain the
......
......@@ -21,7 +21,7 @@ SBIN_SCRIPTS = vlandiff vlansync withadminprivs export_tables cvsupd.pl \
eventping grantnodetype import_commitlog daemon_wrapper \
opsreboot deletenode node_statewait grabwebcams \
grabswitchconfig backupswitches cvsinit checkquota \
spewconlog opsdb_control newnode
spewconlog opsdb_control newnode suchown
WEB_SBIN_SCRIPTS= webnewnode webdeletenode webspewconlog
WEB_BIN_SCRIPTS = webcreate_image websetdest weblinkmon_ctl webspewevents \
......@@ -33,7 +33,7 @@ CTRLSBIN_SCRIPTS= opsdb_control.proxy daemon_wrapper
# These scripts installed setuid, with sudo.
SETUID_BIN_SCRIPTS =
SETUID_SBIN_SCRIPTS = grabwebcams checkquota spewconlog opsdb_control
SETUID_SBIN_SCRIPTS = grabwebcams checkquota spewconlog opsdb_control suchown
SETUID_LIBX_SCRIPTS = xlogin
#
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2007 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use File::Basename;
#
# Forceably chown a directory hierarchy to the real uid of the invoker.
#
sub usage()
{
warn "Usage: $0 <dst>\n";
exit(-1);
}
#
# Configure variables
#
my $TB = "@prefix@";
my $FSDIR_PROJ = "@FSDIR_PROJ@";
my $FSDIR_GROUPS = "@FSDIR_GROUPS@";
my $ARCHIVE_DIR = "/usr/testbed/exparchive";
my $CHOWN = "/usr/sbin/chown";
use lib "@prefix@/lib";
use libdb;
use libtestbed;
use User;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("*** $0:\n".
" Must be setuid! Maybe its a development version?\n");
}
#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
#
if ($UID == 0) {
die("*** $0:\n".
" Please do not run this as root! Its already setuid!\n");
}
# un-taint path
$ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:$TB/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
usage()
if (@ARGV != 1);
my $pathname = $ARGV[0];
#
# Taint check both before and after the realpath call.
#
if ($pathname =~ /^([-\w\/.]+)$/) {
$pathname = $1;
}
else {
die("*** Tainted source: $pathname\n");
}
$pathname = `realpath $pathname`;
if ($pathname =~ /^([-\w\/.]+)$/) {
$pathname = $1;
}
else {
die("*** Tainted translated path: $pathname\n");
}
my $pr = PROJROOT();
my $gr = GROUPROOT();
my $ar = $ARCHIVE_DIR;
if ($pathname =~ /^(($ar|$pr|$FSDIR_PROJ|$gr|$FSDIR_GROUPS)\/[-\w\/.]+)$/) {
$pathname = $1;
}
else {
die("*** $0:\n".
" Destination must be in $pr, $gr, or $ar\n");
}
#
# The user must have write permission on the enclosing directory.
#
my $dir = dirname($pathname);
if (! -W $dir) {
die("*** $0:\n".
" No write permission in '$dir'\n");
}
#
# Chmod to real UID of the invoker.
#
my $this_user = User->ThisUser();
if (! defined($this_user)) {
die("You ($UID) do not exist!\n");
}
my $this_uid = $this_user->uid();
if (system("$CHOWN -R $this_uid $pathname")) {
die("*** $0:\n".
" Failed: '$CHOWN -R $this_uid $pathname'\n");
}
exit(0);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment