spewrpmtar.php3 5.88 KB
Newer Older
1 2
<?php
#
3
# Copyright (c) 2003-2013 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 
# {{{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/>.
# 
# }}}
23 24
#
include("defs.php3");
25
include_once("node_defs.php");
26 27 28 29 30 31 32

function SPITERROR($code, $msg)
{
    header("HTTP/1.0 $code $msg");
    exit();
}

33 34 35 36 37 38 39 40 41 42 43
#
# Capture script errors and report back to user.
#
$session_interactive  = 0;
$session_errorhandler = 'handle_error';

function handle_error($message, $death)
{
    SPITERROR(400, $message);
}

44 45 46
#
# Must be SSL, even though we do not require an account login.
#
47
if (!isset($_SERVER["SSL_PROTOCOL"])) {
48 49 50 51 52
    SPITERROR(400, "Must use https:// to access this page!");
}

#
# Verify page arguments.
53 54 55 56 57 58 59 60
#
$reqargs = RequiredPageArguments("node",    PAGEARG_NODE,
				 "key",     PAGEARG_STRING);
$optargs = OptionalPageArguments("elabinelab_source", PAGEARG_STRING,
				 "file",              PAGEARG_STRING,
				 "stamp",             PAGEARG_INTEGER,
				 "md5",               PAGEARG_STRING,
				 "cvstag",            PAGEARG_STRING);
61 62 63 64 65 66 67 68 69

#
# Move this to ops, except for elabinelab source code with cvstag.
#
if ($SPEWFROMOPS && (! (isset($elabinelab_source) && isset($cvstag)))) {
    $query_string = $_SERVER['QUERY_STRING'];
    header("Location: https://$USERNODE/spewrpmtar?". $query_string);
    return;
}
70
$node_id = $node->node_id();
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87

#
# A variant allows us to pass the Emulab source code back to an ElabInElab
# experiment. 
#
if (!isset($elabinelab_source)) {
    if (!isset($file) ||
	strcmp($file, "") == 0) {
	SPITERROR(400, "You must provide an filename.");
    }
    if (!isset($stamp) || !strcmp($stamp, "")) {
	unset($stamp);
    }
    # We ignore MD5 for now. 
    if (!isset($md5) || !strcmp($md5, "")) {
	unset($md5);
    }
88
}
89 90 91 92

#
# Make sure a reserved node.
#
93 94
if (! ($experiment = $node->Reservation())) {
    SPITERROR(400, "$node_id is not reserved to an experiment!");
95
}
96 97 98 99 100 101 102
if (! ($creator = $experiment->GetCreator())) {
    SPITERROR(400, "Could not map experiment creator to object!");
}
$pid = $experiment->pid();
$eid = $experiment->eid();
$unix_gid = $experiment->UnixGID();
$creator_uid = $creator->uid();
103 104
$project  = $experiment->Project();
$unix_pid = $project->unix_gid();
105 106

#
107
# We need the secret key to match
108
#
109
if (!$experiment->keyhash() || $experiment->keyhash() == "") {
110 111
    SPITERROR(403, "No key defined for this experiment!");
}
112
if ($experiment->keyhash() != $key) {
113 114 115
    SPITERROR(403, "Wrong Key!");
}

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
#
# A cleanup function to keep the child from becoming a zombie, since
# the script is terminated, but the children are left to roam.
#
$fp = 0;

function SPEWCLEANUP()
{
    global $fp;

    if (!$fp || !connection_aborted()) {
	exit();
    }
    pclose($fp);
    exit();
}
ignore_user_abort(1);
register_shutdown_function("SPEWCLEANUP");

135 136 137 138 139 140 141 142
#
# Special case. If requesting elab source code, the experiment must
# be an elabinelab experiment. 
#
if (isset($elabinelab_source)) {
    #
    # Must be an elabinelab experiment of course.
    #
143
    if (! $experiment->elabinelab()) {
144 145 146
	SPITERROR(403, "Not an elabinelab experiment!");
    }

147 148 149 150 151 152 153 154
    #
    # If a specific tag is requested, call out to the spewsource program.
    # Otherwise send it the usual file.
    #
    if (isset($cvstag)) {
	if (! preg_match("/^[-\w\@\/\.]+$/", $cvstag)) {
	    SPITERROR(400, "Invalid characters in cvstag!");
	}
155

156 157
	# Do it anyway.
	$cvstag = escapeshellarg($cvstag);
158

159
	if ($fp = popen("$TBSUEXEC_PATH $creator_uid $unix_pid,$unix_gid ".
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
			"spewsource -t $cvstag", "r")) {
	    header("Content-Type: application/x-gzip");
	    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
	    header("Cache-Control: no-cache, must-revalidate");
	    header("Pragma: no-cache");

	    flush();
	    fpassthru($fp);
	    $fp = 0;
	    flush();
	    return;
	}
	else {
	    SPITERROR(404, "Could not find $file!");
	}
    }
    else {
	if (!is_readable("/usr/testbed/src/emulab-src.tar.gz")) {
	    SPITERROR(404, "Could not find $file!");
	}
	header("Content-Type: application/octet-stream");
	header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
	header("Cache-Control: no-cache, must-revalidate");
	header("Pragma: no-cache");
	flush();
	readfile("/usr/testbed/src/emulab-src.tar.gz");
	exit(0);
187 188 189
    }
}

190 191 192 193
#
# MUST DO THIS!
#
$file   = escapeshellarg($file);
194
$arg    = (isset($stamp) ? "-t " . escapeshellarg($stamp) : "");
195

196 197 198 199 200
#
# Run once with just the verify option to see if the file exists.
# Then do it for real, spitting out the data. Sure, the user could
# delete the file in the meantime, but thats his problem. 
#
201
$retval = SUEXEC($creator_uid, "$unix_pid,$unix_gid",
202
		 "spewrpmtar -v $arg $node_id $file",
203 204
		 SUEXEC_ACTION_IGNORE);

205 206 207 208 209 210 211 212
if ($retval < 0) {
    SUEXECERROR(SUEXEC_ACTION_CONTINUE);
    SPITERROR(500, "Could not verify file!");
}

#
# An expected error.
# 
213
if ($retval) {
214 215 216 217 218
    if ($retval == 2) {
	SPITERROR(304, "File has not changed");
    }
    SPITERROR(404, "Could not verify file: $retval!");
}
219 220 221 222

#
# Okay, now do it for real. 
# 
223
if ($fp = popen("$TBSUEXEC_PATH $creator_uid $unix_pid,$unix_gid ".
224
		"spewrpmtar $node_id $file", "r")) {
225 226 227 228 229 230 231 232 233 234 235 236 237 238
    header("Content-Type: application/octet-stream");
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
    header("Cache-Control: no-cache, must-revalidate");
    header("Pragma: no-cache");

    fpassthru($fp);
    $fp = 0;
    flush();
}
else {
    SPITERROR(404, "Could not find $file!");
}

?>