nscheck.in 4.27 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
use English;
use Getopt::Std;
28
use Cwd qw(realpath);
29 30 31 32 33 34

#
# Syntax check an NS file.
#
# usage: nscheck <nsfile>
#
35 36 37 38 39
# Exit value is important; 
# $status < 0 - Fatal error. Something went wrong we did not expect.
# $status = 0 - Parsed okay.
# $status > 0 - Parse error. 
#
40 41 42 43 44 45 46
sub usage()
{
    print STDOUT "Usage: nscheck <nsfile>\n";
    exit(-1);
}
my  $optlist = "";

47 48 49
#
# Function phototype(s)
#
50
sub fatal($;$);
51

52 53 54 55
#
# Configure variables
#
my $TB       = "@prefix@";
56
my $parser   = "$TB/libexec/parse-ns";
57
my $status   = 0;
58
my $dirname;
59
my $ISFS     = ("@BOSSNODE_IP@" eq "@FSNODE_IP@") ? 1 : 0;
60

61 62 63 64
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
65
use libtestbed;
66 67
use libtblog;

68 69 70 71 72 73 74 75
#
# Turn off line buffering on output
#
$| = 1;

#
# Untaint the path
# 
76
$ENV{'PATH'} = "/bin:/usr/bin:/sbin:/usr/sbin";
77 78 79 80 81 82 83 84 85 86 87 88 89
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# Parse command arguments. Once we return from getopts, all that should
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (@ARGV != 1) {
    usage();
}
Leigh Stoller's avatar
Leigh Stoller committed
90
my ($tempfile) = @ARGV;
91 92 93 94 95

#
# Untaint the arguments.
#
# Note different taint check (allow /).
96
if ($tempfile =~ /^([-\w\.\/]+)$/) {
97 98 99 100 101 102
    $tempfile = $1;
}
else {
    fatal("Tainted argument $tempfile");
}

103 104 105 106 107
#
# Called from ops interactively. Make sure NS file in /proj or /users.
#
# Use realpath to resolve any symlinks.
#
108
my $translated = realpath($tempfile);
109 110 111
if (!defined($translated)) {
    fatal("No such file: $tempfile\n");
}
112 113 114 115 116 117 118 119
if ($translated =~ /^([-\w\.\/]+)$/) {
    $tempfile = $1;
}
else {
    fatal("Tainted nsfile returned by realpath: $translated\n");
}

#
120 121 122 123 124 125
# The file must reside in an acceptible location. Since this script
# runs as the caller, regular file permission checks ensure it is a
# file the user is allowed to use.  So we don't have to be too tight
# with the RE matching /tmp and /var/tmp files.  Note that
# /tmp/$pid-$eid.nsfile.XXXXX is also allowed since this script is
# invoked directly from web interface.
126
#
127 128
if (! ($tempfile =~ /^\/tmp\/[-\w]+-\d+\.nsfile/) &&
    ! ($tempfile =~ /^\/var\/tmp\/php\w+/) &&
129
    ! ($tempfile =~ /^\/tmp\/php\w+/) &&
130
    ! TBValidUserDir($tempfile, $ISFS)) {
131 132 133
    fatal("$tempfile does not resolve to an appropriate directory!\n");
}

134 135
$nsfile    = "foo.ns";

136 137
# Check for existence of NS file and exit with error such that web
# interface tells the user (positive exit value).
138
if (! -f $tempfile || ! -r $tempfile || -z $tempfile) {
139 140 141 142 143
    print STDERR "*** $0:\n".
	         "    $tempfile does not exist or is not a readable file!\n";
    exit(1);
}

144 145 146 147 148 149 150 151 152
#
# Make a temp dir and copy the NS file into it. We run the scripts
# from that directory cause it writes temp files.
# 
$dirname = "/tmp/parse-$$";

mkdir($dirname, 0775) or
    fatal("Could not mkdir $dirname");

153
if (system("/bin/cp", "$tempfile", "$dirname/$nsfile")) {
154 155 156
    fatal("Could not copy $tempfile to $dirname");
}

157 158 159
chdir($dirname) or
    fatal("Could not chdir to $dirname");

160
#
Leigh Stoller's avatar
Leigh Stoller committed
161 162
# Run parse in impotent mode on the NS file.  This has no effect but
# will display any errors.
163 164 165
#
# Be sure to exit with >0 staus
#
Leigh Stoller's avatar
Leigh Stoller committed
166

167
if (system("$parser -n -a $nsfile") != 0) {
168 169 170
    tberror({type => 'secondary', severity => SEV_SECONDARY,
	     error => ['ns_parse_failed']},
	    "NS Parse failed!");
171
    $status = 1;
172 173 174
}

system("/bin/rm", "-rf", "$dirname");
175
exit $status;
176

177
sub fatal($;$)
178
{
179 180
    my $parms = {};
    $parms = shift if ref $_[0] eq 'HASH';
181 182
    my($mesg) = $_[0];

183 184
    system("/bin/rm", "-rf", "$dirname")
	if (defined($dirname));
185

186
    tbdie($parms, $mesg);
187
}