Project

General

Profile

Download (12.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	system_firmware.php
4
*/
5
/* ====================================================================
6
 *	Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
7
 *
8
 *	Some or all of this file is based on the m0n0wall project which is
9
 *	Copyright (c)  2004 Manuel Kasper (BSD 2 clause)
10
 *
11
 *	Redistribution and use in source and binary forms, with or without modification,
12
 *	are permitted provided that the following conditions are met:
13
 *
14
 *	1. Redistributions of source code must retain the above copyright notice,
15
 *		this list of conditions and the following disclaimer.
16
 *
17
 *	2. Redistributions in binary form must reproduce the above copyright
18
 *		notice, this list of conditions and the following disclaimer in
19
 *		the documentation and/or other materials provided with the
20
 *		distribution.
21
 *
22
 *	3. All advertising materials mentioning features or use of this software
23
 *		must display the following acknowledgment:
24
 *		"This product includes software developed by the pfSense Project
25
 *		 for use in the pfSense software distribution. (http://www.pfsense.org/).
26
 *
27
 *	4. The names "pfSense" and "pfSense Project" must not be used to
28
 *		 endorse or promote products derived from this software without
29
 *		 prior written permission. For written permission, please contact
30
 *		 coreteam@pfsense.org.
31
 *
32
 *	5. Products derived from this software may not be called "pfSense"
33
 *		nor may "pfSense" appear in their names without prior written
34
 *		permission of the Electric Sheep Fencing, LLC.
35
 *
36
 *	6. Redistributions of any form whatsoever must retain the following
37
 *		acknowledgment:
38
 *
39
 *	"This product includes software developed by the pfSense Project
40
 *	for use in the pfSense software distribution (http://www.pfsense.org/).
41
 *
42
 *	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
43
 *	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 *	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
45
 *	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
46
 *	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47
 *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48
 *	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
49
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50
 *	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
51
 *	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
52
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
53
 *	OF THE POSSIBILITY OF SUCH DAMAGE.
54
 *
55
 *	====================================================================
56
 *
57
 */
58
/*
59
	pfSense_BUILDER_BINARIES:	/usr/bin/tar
60
	pfSense_MODULE: firmware
61
*/
62

    
63
##|+PRIV
64
##|*IDENT=page-system-firmware-manualupdate
65
##|*NAME=System: Firmware: Manual Update page
66
##|*DESCR=Allow access to the 'System: Firmware: Manual Update' page.
67
##|*MATCH=system_firmware.php*
68
##|-PRIV
69

    
70
$d_isfwfile = 1;
71
$nocsrf = true;
72

    
73
require_once("globals.inc");
74
require_once("functions.inc");
75
require_once("guiconfig.inc");
76
require_once("xmlrpc_client.inc");
77

    
78
$curcfg = $config['system']['firmware'];
79

    
80
/* Allow additional execution time 0 = no limit. */
81
ini_set('max_execution_time', '9999');
82
ini_set('max_input_time', '9999');
83

    
84
function file_is_for_platform($filename, $ul_name) {
85
	global $g;
86
	if ($g['platform'] == "nanobsd") {
87
		if (stristr($ul_name, "nanobsd")) {
88
			return true;
89
		} else {
90
			return false;
91
		}
92
	}
93
	$_gb = exec("/usr/bin/tar xzf $filename -C /tmp/ etc/platform");
94
	unset($_gb);
95
	if (!file_exists("/tmp/etc/platform")) {
96
		return false;
97
	}
98
	$upgrade_is_for_platform = trim(file_get_contents("/tmp/etc/platform", " \n\t\r"));
99
	if ($g['platform'] == $upgrade_is_for_platform) {
100
		@unlink("/tmp/etc/platform");
101
		return true;
102
	}
103
	return false;
104
}
105

    
106
function file_upload_error_message($error_code) {
107
	switch ($error_code) {
108
		case UPLOAD_ERR_INI_SIZE:
109
			return gettext('The uploaded file exceeds the upload_max_filesize directive in php.ini');
110
		case UPLOAD_ERR_FORM_SIZE:
111
			return gettext('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form');
112
		case UPLOAD_ERR_PARTIAL:
113
			return gettext('The uploaded file was only partially uploaded');
114
		case UPLOAD_ERR_NO_FILE:
115
			return gettext('No file was uploaded');
116
		case UPLOAD_ERR_NO_TMP_DIR:
117
			return gettext('Missing a temporary folder');
118
		case UPLOAD_ERR_CANT_WRITE:
119
			return gettext('Failed to write file to disk');
120
		case UPLOAD_ERR_EXTENSION:
121
			return gettext('File upload stopped by extension');
122
		default:
123
			return gettext('Unknown upload error');
124
	}
125
}
126

    
127
/* if upgrade in progress, alert user */
128
if (is_subsystem_dirty('firmwarelock')) {
129
	$pgtitle = array(gettext("System"), gettext("Firmware"), gettext("Manual Update"));
130
	include("head.inc");
131
	include("fbegin.inc");
132
	print_info_box(gettext("An upgrade is currently in progress. The firewall will reboot when the operation is complete."));
133
	include("foot.inc");
134
	exit;
135
}
136

    
137
if ($_POST['backupbeforeupgrade']) {
138
	touch("/tmp/perform_full_backup.txt");
139
}
140

    
141
/* Handle manual upgrade */
142
if ($_POST && !is_subsystem_dirty('firmwarelock')) {
143

    
144
	unset($input_errors);
145
	unset($sig_warning);
146

    
147
	if (stristr($_POST['Submit'], gettext("Enable"))) {
148
		$mode = "enable";
149
	} else if (stristr($_POST['Submit'], gettext("Disable"))) {
150
		$mode = "disable";
151
	} else if (stristr($_POST['Submit'], gettext("Upgrade")) || $_POST['sig_override']) {
152
		$mode = "upgrade";
153
	} else if ($_POST['sig_no']) {
154
		if (file_exists("{$g['upload_path']}/firmware.tgz")) {
155
			unlink("{$g['upload_path']}/firmware.tgz");
156
		}
157
	}
158
	if ($mode) {
159
		if ($mode == "enable") {
160
			conf_mount_rw();
161
			mark_subsystem_dirty('firmware');
162
		} else if ($mode == "disable") {
163
			conf_mount_ro();
164
			clear_subsystem_dirty('firmware');
165
		} else if ($mode == "upgrade") {
166
			if ($_FILES['ulfile']['error']) {
167
				$errortext = "(" . file_upload_error_message($_FILES['ulfile']['error']) . ")";
168
			}
169
			if (is_uploaded_file($_FILES['ulfile']['tmp_name'])) {
170
				/* verify firmware image(s) */
171
				if (file_is_for_platform($_FILES['ulfile']['tmp_name'], $_FILES['ulfile']['name']) == false && !$_POST['sig_override']) {
172
					$input_errors[] = gettext("The uploaded image file is not for this platform.");
173
				} else if (!file_exists($_FILES['ulfile']['tmp_name'])) {
174
					/* probably out of memory for the MFS */
175
					$input_errors[] = gettext("Image upload failed (out of memory?)");
176
					mwexec("/etc/rc.firmware disable");
177
					clear_subsystem_dirty('firmware');
178
				} else {
179
					/* move the image so PHP won't delete it */
180
					rename($_FILES['ulfile']['tmp_name'], "{$g['upload_path']}/firmware.tgz");
181

    
182
					/* check digital signature */
183
					$sigchk = verify_digital_signature("{$g['upload_path']}/firmware.tgz");
184

    
185
					if ($sigchk == 1) {
186
						$sig_warning = gettext("The digital signature on this image is invalid.");
187
					} else if ($sigchk == 2 && !isset($config['system']['firmware']['allowinvalidsig'])) {
188
						$sig_warning = gettext("This image is not digitally signed.");
189
					} else if (($sigchk >= 3)) {
190
						$sig_warning = gettext("There has been an error verifying the signature on this image.");
191
					}
192

    
193
					if (!verify_gzip_file("{$g['upload_path']}/firmware.tgz")) {
194
						$input_errors[] = gettext("The image file is corrupt.");
195
						unlink("{$g['upload_path']}/firmware.tgz");
196
					}
197
				}
198
			}
199

    
200
			run_plugins("/usr/local/pkg/firmware_upgrade");
201

    
202
			/* Check for input errors, firmware locks, warnings, then check for firmware if sig_override is set */
203
			if (!$input_errors && !is_subsystem_dirty('firmwarelock') && (!$sig_warning || $_POST['sig_override'])) {
204
				if (file_exists("{$g['upload_path']}/firmware.tgz")) {
205
					/* fire up the update script in the background */
206
					mark_subsystem_dirty('firmwarelock');
207
					$savemsg = gettext("The firmware is now being updated. The firewall will reboot automatically.");
208
					if (stristr($_FILES['ulfile']['name'], "nanobsd") or $_POST['isnano'] == "yes") {
209
						mwexec_bg("/etc/rc.firmware pfSenseNanoBSDupgrade {$g['upload_path']}/firmware.tgz");
210
					} else {
211
						if ($g['platform'] == "nanobsd") {
212
							$whichone = "pfSenseNanoBSDupgrade";
213
						} else {
214
							$whichone = "pfSenseupgrade";
215
						}
216
						mwexec_bg("/etc/rc.firmware {$whichone} {$g['upload_path']}/firmware.tgz");
217
						unset($whichone);
218
					}
219
				} else {
220
					$savemsg = sprintf(gettext("Firmware image missing or other error, please try again %s."), $errortext);
221
				}
222
			}
223
		}
224
	}
225
}
226

    
227
$pgtitle = array(gettext("System"), gettext("Firmware"));
228
include("head.inc");
229

    
230
if ($input_errors)
231
	print_input_errors($input_errors);
232

    
233
if ($savemsg)
234
	print_info_box($savemsg);
235

    
236
if ($fwinfo != "")
237
	print_info_box($fwinfo);
238

    
239
$tab_array = array();
240
$tab_array[] = array(gettext("Manual Update"), true, "system_firmware.php");
241
$tab_array[] = array(gettext("Auto Update"), false, "system_firmware_check.php");
242
$tab_array[] = array(gettext("Updater Settings"), false, "system_firmware_settings.php");
243
if($g['hidedownloadbackup'] == false)
244
	$tab_array[] = array(gettext("Restore Full Backup"), false, "system_firmware_restorefullbackup.php");
245

    
246
display_top_tabs($tab_array);
247

    
248
// For a simple yes/no we can use an HTML form
249
if ($sig_warning && !$input_errors) {
250
	$sig_warning = gettext("The image you uploaded " .
251
		"is not an official/supported image and may lead to unexpected behavior or security " .
252
		"compromises. Only install images that come from sources that you trust, and make sure ".
253
		"that the image has not been tampered with.") . "<br /><br />".
254
		gettext("Do you want to install this image anyway (on your own risk)?");
255

    
256
	print_info_box($sig_warning);
257
?>
258
	<form action="system_firmware.php" method="post" enctype="multipart/form-data">
259
		<input name="sig_override" type="submit" class="btn btn-danger" id="sig_override" value=" <?=gettext("Yes");?> " />
260
		<input name="sig_no" type="submit" class="btn btn-default" id="sig_no" value=" <?=gettext("No"); ?> " />
261
	</form>
262
<?php
263

    
264
} else {
265
	// This is where the work gets done so Forms.classes will be used from this point
266
	if (!is_subsystem_dirty('firmwarelock')) {
267
		require_once('classes/Form.class.php');
268

    
269
		if (!is_subsystem_dirty('rebootreq')) {
270
			// Provide a button to enable firmware upgrades. Upgrades should be disabled on initial page load
271
			if (!is_subsystem_dirty('firmware') || !$_POST || $_POST['save']) {
272
				$enablebtn = new Form_Button(
273
					'Submit',
274
					'Enable firmware upload'
275
					);
276

    
277
				$enablebtn->addClass('btn-warning');
278
				$form = new Form($enablebtn);
279
				$section = new Form_Section('Invoke ' . $g['product_name'] .' Manual Upgrade');
280
				$section->addInput(new Form_StaticText('Enable', 'Click the "Enable firmware upload" button below to begin.'));
281
			}
282
			else {
283
				// Upgrades are now enabled
284
				$form = new Form('Disable firmware upload');
285

    
286
				$form->setMultipartEncoding();
287

    
288
				$section = new Form_Section('Perform ' . $g['product_name'] .' Manual Upgrade');
289

    
290
				if (!session_id())
291
					$upload_id = uniqid();
292
				else
293
					$upload_id = session_id();
294

    
295
				$section->addInput(new Form_Input(
296
					'UPLOAD_IDENTIFIER',
297
					'',
298
					'hidden',
299
					$upload_id
300
					));
301

    
302
				if(stristr($_FILES['ulfile']['name'],"nanobsd")) {
303
					$section->addInput(new Form_Input(
304
						'isnano',
305
						'',
306
						'hidden',
307
						'yes'
308
						));
309
				}
310

    
311
				if ($g['platform'] == "nanobsd")
312
					$type = "*.img.gz";
313
				else
314
					$type = "*.tgz";
315

    
316
				$filepicker = new Form_Input(
317
					'ulfile',
318
					'File to upload (' . $type . ')',
319
					'file',
320
					''
321
				);
322

    
323
				$section->addInput($filepicker)->setHelp('Choose the file you wish to upload');
324

    
325
				if ($g['hidebackupbeforeupgrade'] === false) {
326
					$section->addInput(new Form_Checkbox(
327
						'backupbeforeupgrade',
328
						Backup,
329
						'Perform a full backup prior to upgrade',
330
						false
331
					));
332
				}
333

    
334
				$section->addInput(new Form_Button(
335
					'Submit',
336
					'Upgrade firmware'
337
				))->addClass('btn-danger btn-sm')->setHelp('Click the "Upgrade firmware" button above to start the upgrade process');
338
			}
339

    
340
			$form->add($section);
341
			print($form);
342
		}
343
	}
344
	else {
345
		print_info_box('<strong>' . gettext("You must reboot the system before you can upgrade the firmware.") . '</strong>');
346
	}
347

    
348
	if (is_subsystem_dirty('firmware') && !is_subsystem_dirty('firmwarelock')) {
349
		print_info_box('<strong>' . gettext("DO NOT ") . '</strong>' . gettext('abort the firmware upgrade once it ' .
350
			'has started. The firewall will reboot automatically after ' .
351
			'storing the new firmware. The configuration will be maintained.'));
352
	}
353
}
354

    
355
include("foot.inc"); ?>
(197-197/234)