console_setup.proxy.in 5.26 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh Stoller's avatar
Leigh Stoller committed
2 3

#
4
# Copyright (c) 2000-2014 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
Leigh Stoller's avatar
Leigh Stoller committed
24 25
#

26 27 28
use English;

#
29 30 31 32 33 34 35
# usage: console_setup.proxy tipname group tipname group ...
#
# This script runs on the tip servers, which is where the capture processes
# are running. Since the tip servers do not have direct access to the DB
# this invoked from the boss node. For each tip device, specify the group
# the associated files should be in. This script will send the proper signal
# to the capture process, and then reset the files to the proper group.
36 37
#
#
38
my $TIPLOGDIR   = "/usr/testbed/log/tiplogs";
39 40
my $TIPDEVDIR   = "/dev/tip";
my $dbg		= 1;
41
my %tipgroup    = ();
42
my $failures    = 0;
43 44 45 46 47 48

# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

sub usage {
49
    die("Usage: console_setup.proxy tipname group [tipname group ...]\n");
50 51 52 53 54 55 56 57 58 59 60
}

if ( $#ARGV < 1) {
    usage();
}

while ($#ARGV >= 0) {
    if ($#ARGV < 1) {
	usage();
    }
    
61 62
    $name = shift;
    $grp  = shift;
63 64

    # untaint the args.
65 66
    if ($name =~ /^([-\@\w.]+)$/) {
	$name = $1;
67
    }
68 69
    if ($grp =~ /^([-\@\w.]+)$/) {
	$grp = $1;
70 71
    }
    
72
    $tipgroup{$name} = $grp;
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
}

#
# This script must be run as root, typically from paper.
#
if ($UID != 0) {
    die("Must be run as root.");
}

if (! chdir($TIPLOGDIR)) {
    die("Could not chdir to $TIPLOGDIR: $!\n");
}

#
# Well, do it.
# 
89 90 91 92 93
foreach my $tipname ( keys %tipgroup ) {
    my $grp        = $tipgroup{$tipname};
    my $filename   = "${tipname}.run";
    my $tipdevname = "$TIPDEVDIR/$tipname";
    my $aclname    = "${tipname}.acl";
94 95 96 97 98

    #
    # Find out the current group setting for the file. 
    #
    if (! -e $filename) {
99
	print STDERR
100
	    "*** Console log for $tipname does not exist! Skipping ...\n";
101 102
	$failures++;
	next;
103 104 105 106 107 108 109 110 111
    }
    # This is silly! Is there a better way to do this?
    (undef,undef,undef,undef,undef,$gid) = stat($filename);

    #
    # If the file is already in the correct group skip it since there no point
    # in rolling the file. Inconvenient for the user to have the log keep
    # rolling.
    #
112 113
    my ($cgrp) = getgrgid($gid);
    if (defined($cgrp) && $cgrp eq $grp) {
114
	goto setperms;
115 116 117 118 119 120
    }

    unlink($filename) or
	die("Could not unlink run file $filename");

    #
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
    # Unlink this so current user gets old version not new one. 
    # 
    if (-e $aclname) {
	unlink($aclname) or
	    die("Could not unlink run file $aclname");
    }

    #
    # Remove group access from the tty device.  This renders the device
    # inaccessible to both old and new users while we revoke access from
    # any current tip user.
    #
    if (-e $tipdevname) {
	chmod(0600, $tipdevname) or
	    die("Could not chmod(0600) $tipdevname: $!");
    }

    #
    # Now send a USR2 signal to the capture process. This will shutdown
    # any attached tip, and reopen the run file.
141
    #
142
    $procid = `cat ${tipname}.pid`;
143 144
    die("Error obtaining pid for $tipname\n")
	if ($?);
145 146 147 148 149
    $procid =~ s/\n//;
    # untaint
    if ($procid =~ /^([-\@\w.]+)$/) {
	$procid = $1;
    }
150 151
    kill('USR2', $procid) or
	die("Could not signal(USR2) process $procid for log $filename");
152
    # Give capture the chance to react.
153
    # Don't use sleep cause 1 second too long wait when doing 25 devices!
154
    select(undef, undef, undef, 0.2);
155 156 157 158 159 160 161 162 163 164 165 166 167

    #
    # If the file does not exist, touch it. We have this problem with
    # capture getting blocked.
    #
    if (! -e $filename) {
	system("touch $filename");
    }
    
    #
    # The new log should exist now. Set its group, and just to be safe
    # set its mode too. 
    #
168
    $gid = getgrnam($grp);
169 170 171 172 173 174
    if (!defined($gid)) {
	print STDERR "*** Group '$grp' does not exist, ".
	    "console for $tipname will not be available\n";
	$grp = "wheel";
	$gid = 0;
    }
175 176 177 178 179 180
    chown(0, $gid, $filename) or
	die("Could not chown(0, $gid) $filename: $!");
    chmod(0640, $filename) or
	die("Could not chmod(0640) $filename: $!");

    #
181 182 183
    # Set the mode and group on the tty that tip is going to use. This
    # allows the new group to access the tip line using a non-setuid/gid
    # program.
184
    #
185
  setperms:
186 187 188 189 190 191
    if (-e $tipdevname) {
	chown(0, $gid, $tipdevname) or
	    die("Could not chown(0, $gid) $tipdevname: $!");
	chmod(0660, $tipdevname) or
	    die("Could not chmod(0660) $tipdevname: $!");
    }
192 193 194 195 196 197 198

    #
    # Ditto for "acl" file, which new tip needs access to.
    # 
    if (-e $aclname) {
	chown(0, $gid, $aclname) or
	    die("Could not chown(0, $gid) $aclname: $!");
Leigh Stoller's avatar
Leigh Stoller committed
199
	chmod(0640, $aclname) or
200 201
	    die("Could not chmod(0660) $aclname: $!");
    }
202 203
}

204
# Don't worry about failures. Non-fatal.
205
exit 0;