nscheck.in 3.46 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2 3 4

#
# EMULAB-COPYRIGHT
5
# Copyright (c) 2000-2004 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
6 7 8
# All rights reserved.
#

9 10 11 12 13 14 15 16
use English;
use Getopt::Std;

#
# Syntax check an NS file.
#
# usage: nscheck <nsfile>
#
17 18 19 20 21
# Exit value is important; 
# $status < 0 - Fatal error. Something went wrong we did not expect.
# $status = 0 - Parsed okay.
# $status > 0 - Parse error. 
#
22 23 24 25 26 27 28
sub usage()
{
    print STDOUT "Usage: nscheck <nsfile>\n";
    exit(-1);
}
my  $optlist = "";

29 30 31
#
# Function phototype(s)
#
32
sub fatal($;$);
33

34 35 36 37
#
# Configure variables
#
my $TB       = "@prefix@";
38
my $parser   = "$TB/libexec/parse-ns";
39
my $status   = 0;
40
my $dirname;
41

42 43 44 45 46 47
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libtblog;

48 49 50 51 52 53 54 55
#
# Turn off line buffering on output
#
$| = 1;

#
# Untaint the path
# 
56
$ENV{'PATH'} = "/bin:/usr/bin:/sbin:/usr/sbin";
57 58 59 60 61 62 63 64 65 66 67 68 69
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 B. Stoller's avatar
Leigh B. Stoller committed
70
my ($tempfile) = @ARGV;
71 72 73 74 75

#
# Untaint the arguments.
#
# Note different taint check (allow /).
76
if ($tempfile =~ /^([-\w\.\/]+)$/) {
77 78 79 80 81 82
    $tempfile = $1;
}
else {
    fatal("Tainted argument $tempfile");
}

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
#
# Called from ops interactively. Make sure NS file in /proj or /users.
#
# Use realpath to resolve any symlinks.
#
my $translated = `realpath $tempfile`;
if ($translated =~ /^([-\w\.\/]+)$/) {
    $tempfile = $1;
}
else {
    fatal("Tainted nsfile returned by realpath: $translated\n");
}

#
# The file must reside in /proj, /groups, or /users. Since this script
# runs as the caller, regular file permission checks ensure its a file
# the user is allowed to use. /tmp/$guid-$nsref.nsfile also allowed
# since this script is invoked directly from web interface, which generates
# a name that should not be guessable, so as long as it looks to be in
# proper format, we accept it. 
#
104 105
if (! ($tempfile =~ /^\/tmp\/[-\w]+-\d+\.nsfile/) &&
    ! ($tempfile =~ /^\/var\/tmp\/php\w+/) &&
106 107 108 109 110 111
    ! ($tempfile =~ /^\/proj/) &&
    ! ($tempfile =~ /^\/groups/) &&
    ! ($tempfile =~ /^\/users/)) {
    fatal("$tempfile does not resolve to an appropriate directory!\n");
}

112 113
$nsfile    = "foo.ns";

114 115
# Check for existence of NS file and exit with error such that web
# interface tells the user (positive exit value).
116
if (! -f $tempfile || ! -r $tempfile || -z $tempfile) {
117 118 119 120 121
    print STDERR "*** $0:\n".
	         "    $tempfile does not exist or is not a readable file!\n";
    exit(1);
}

122 123 124 125 126 127 128 129 130
#
# 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");

131
if (system("/bin/cp", "$tempfile", "$dirname/$nsfile")) {
132 133 134
    fatal("Could not copy $tempfile to $dirname");
}

135 136 137
chdir($dirname) or
    fatal("Could not chdir to $dirname");

138
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
139 140
# Run parse in impotent mode on the NS file.  This has no effect but
# will display any errors.
141 142 143
#
# Be sure to exit with >0 staus
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
144

145
if (system("$parser -n -a $nsfile") != 0) {
146 147 148
    tberror({type => 'secondary', severity => SEV_SECONDARY,
	     error => ['ns_parse_failed']},
	    "NS Parse failed!");
149
    $status = 1;
150 151 152
}

system("/bin/rm", "-rf", "$dirname");
153
exit $status;
154

155
sub fatal($;$)
156
{
157 158
    my $parms = {};
    $parms = shift if ref $_[0] eq 'HASH';
159 160
    my($mesg) = $_[0];

161 162
    system("/bin/rm", "-rf", "$dirname")
	if (defined($dirname));
163

164
    tbdie($parms, $mesg);
165
}