Project

General

Profile

Download (15.7 KB) Statistics
| Branch: | Tag: | Revision:
1 054f0ed0 Steve Beaver
<?php
2
/*
3 587315d5 Steve Beaver
 * services_acb.php
4 054f0ed0 Steve Beaver
 *
5
 * part of pfSense (https://www.pfsense.org)
6 38809d47 Renato Botelho do Couto
 * Copyright (c) 2008-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8 402c98a2 Reid Linnemann
 * Copyright (c) 2014-2023 Rubicon Communications, LLC (Netgate)
9 054f0ed0 Steve Beaver
 * All rights reserved.
10
 *
11
 * Licensed under the Apache License, Version 2.0 (the "License");
12
 * you may not use this file except in compliance with the License.
13
 * You may obtain a copy of the License at
14
 *
15
 * http://www.apache.org/licenses/LICENSE-2.0
16
 *
17
 * Unless required by applicable law or agreed to in writing, software
18
 * distributed under the License is distributed on an "AS IS" BASIS,
19
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 * See the License for the specific language governing permissions and
21
 * limitations under the License.
22
 */
23 18c1de41 jim-p
24
##|+PRIV
25
##|*IDENT=page-services-acb
26
##|*NAME=Services: Auto Config Backup: Restore
27
##|*DESCR=Restore from auto config backup.
28
##|*MATCH=services_acb.php*
29
##|-PRIV
30
31 054f0ed0 Steve Beaver
require("guiconfig.inc");
32
require("acb.inc");
33
34
// Separator used during client / server communications
35
$oper_sep = "\|\|";
36
$exp_sep = '||';
37
38
// Encryption password
39 1e45d13f Christian McDonald
$decrypt_password = config_get_path('system/acb/encryption_password');
40 054f0ed0 Steve Beaver
41
// Defined username. Username must be sent lowercase. See Redmine #7127 and Netgate Redmine #163
42 404efa21 jim-p
$username = strtolower(config_get_path('system/acb/gold_username'));
43 1e45d13f Christian McDonald
$password = config_get_path('system/acb/gold_password');
44 054f0ed0 Steve Beaver
45
// Set hostname
46
if ($_REQUEST['hostname']) {
47
	$hostname = $_REQUEST['hostname'];
48
} else {
49 404efa21 jim-p
	$hostname = config_get_path('system/hostname') . "." . config_get_path('system/domain');
50 054f0ed0 Steve Beaver
}
51
52
// Hostname of local machine
53 404efa21 jim-p
$myhostname = config_get_path('system/hostname') . "." . config_get_path('system/domain');
54 054f0ed0 Steve Beaver
55
if (!$decrypt_password) {
56 af0edce6 Steve Beaver
	Header("Location: /services_acb_settings.php");
57 054f0ed0 Steve Beaver
	exit;
58
}
59
60
if ($_REQUEST['savemsg']) {
61
	$savemsg = htmlentities($_REQUEST['savemsg']);
62
}
63
64
if ($_REQUEST['download']) {
65
	$pgtitle = array("Services", "Auto Configuration Backup", "Revision Information");
66
} else {
67
	$pgtitle = array("Services", "Auto Configuration Backup", "Restore");
68
}
69
70
/* Set up time zones for conversion. See #5250 */
71
$acbtz = new DateTimeZone('America/Chicago');
72
$mytz = new DateTimeZone(date_default_timezone_get());
73
74
include("head.inc");
75
76
77
if ($_REQUEST['rmver'] != "") {
78
	$curl_session = curl_init();
79 f01c0991 Steve Beaver
	curl_setopt($curl_session, CURLOPT_URL, "https://acb.netgate.com/rmbkp");
80
	curl_setopt($curl_session, CURLOPT_POSTFIELDS, "userkey=" . $userkey .
81 054f0ed0 Steve Beaver
		"&revision=" . urlencode($_REQUEST['rmver']) .
82 2568e151 Christian McDonald
		"&version=" . g_get('product_version') .
83 054f0ed0 Steve Beaver
		"&uid=" . urlencode($uniqueID));
84
	curl_setopt($curl_session, CURLOPT_POST, 3);
85
	curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
86
	curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
87 2568e151 Christian McDonald
	curl_setopt($curl_session, CURLOPT_USERAGENT, g_get('product_label') . '/' . rtrim(file_get_contents("/etc/version")));
88 054f0ed0 Steve Beaver
	// Proxy
89 75a3b0de Viktor G
	set_curlproxy($curl_session);
90 054f0ed0 Steve Beaver
91
	$data = curl_exec($curl_session);
92
	if (curl_errno($curl_session)) {
93
		$fd = fopen("/tmp/acb_deletedebug.txt", "w");
94 8a6d9d7f Steve Beaver
		fwrite($fd, "https://acb.netgate.com/rmbkp" . "" . "action=delete&hostname=" . urlencode($hostname) . "&revision=" . urlencode($_REQUEST['rmver']) . "\n\n");
95 054f0ed0 Steve Beaver
		fwrite($fd, $data);
96
		fwrite($fd, curl_error($curl_session));
97
		fclose($fd);
98 8a6d9d7f Steve Beaver
		$savemsg = "An error occurred while trying to remove the item from acb.netgate.com.";
99 054f0ed0 Steve Beaver
	} else {
100
		curl_close($curl_session);
101
		$budate = new DateTime($_REQUEST['rmver'], $acbtz);
102
		$budate->setTimezone($mytz);
103
		$savemsg = "Backup revision " . htmlspecialchars($budate->format(DATE_RFC2822)) . " has been removed.";
104
	}
105
}
106
107
if ($_REQUEST['newver'] != "") {
108
	// Phone home and obtain backups
109
	$curl_session = curl_init();
110
111 f01c0991 Steve Beaver
	curl_setopt($curl_session, CURLOPT_URL, "https://acb.netgate.com/getbkp");
112
	curl_setopt($curl_session, CURLOPT_POSTFIELDS, "userkey=" . $userkey .
113
		"&revision=" . urlencode($_REQUEST['newver']) .
114 2568e151 Christian McDonald
		"&version=" . g_get('product_version') .
115 f01c0991 Steve Beaver
		"&uid=" . urlencode($uniqueID));
116 054f0ed0 Steve Beaver
	curl_setopt($curl_session, CURLOPT_POST, 3);
117
	curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
118
	curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
119 2568e151 Christian McDonald
	curl_setopt($curl_session, CURLOPT_USERAGENT, g_get('product_label') . '/' . rtrim(file_get_contents("/etc/version")));
120 054f0ed0 Steve Beaver
	// Proxy
121 75a3b0de Viktor G
	set_curlproxy($curl_session);
122 054f0ed0 Steve Beaver
	$data = curl_exec($curl_session);
123
	$data_split = explode('++++', $data);
124
	$sha256 = trim($data_split[0]);
125
	$data = $data_split[1];
126
127
	if (!tagfile_deformat($data, $data, "config.xml")) {
128
		$input_errors[] = "The downloaded file does not appear to contain an encrypted pfSense configuration.";
129
	}
130
131
	$out = decrypt_data($data, $decrypt_password);
132 5efa3d45 jim-p
	if (!strstr($out, "pfsense") ||
133
	    (strlen($out) < 50)) {
134
		$out = "Could not decrypt. Different encryption key?";
135
		$input_errors[] = "Could not decrypt config.xml. Check the encryption key and try again: {$out}";
136
	} else {
137
		$pos = stripos($out, "</pfsense>");
138
		$data = substr($out, 0, $pos);
139
		$data = $data . "</pfsense>\n";
140 054f0ed0 Steve Beaver
141 5efa3d45 jim-p
		$fd = fopen("/tmp/config_restore.xml", "w");
142 054f0ed0 Steve Beaver
		fwrite($fd, $data);
143
		fclose($fd);
144
145 5efa3d45 jim-p
		$ondisksha256 = trim(shell_exec("/sbin/sha256 /tmp/config_restore.xml | /usr/bin/awk '{ print $4 }'"));
146
		// We might not have a sha256 on file for older backups
147
		if ($sha256 != "0" && $sha256 != "") {
148
			if ($ondisksha256 != $sha256) {
149
				$input_errors[] = "SHA256 values do not match, cannot restore. $ondisksha256 != $sha256";
150
			}
151
		}
152
		if (curl_errno($curl_session)) {
153
			/* If an error occurred, log the error in /tmp/ */
154
			$fd = fopen("/tmp/acb_restoredebug.txt", "w");
155
			fwrite($fd, "https://acb.netgate.com/getbkp" . "" . "action=restore&hostname={$hostname}&revision=" . urlencode($_REQUEST['newver']) . "\n\n");
156
			fwrite($fd, $data);
157
			fwrite($fd, curl_error($curl_session));
158
			fclose($fd);
159
		} else {
160
			curl_close($curl_session);
161
		}
162
163
		if (!$input_errors && $data) {
164
			if (config_restore("/tmp/config_restore.xml") == 0) {
165
				$savemsg = "Successfully reverted the pfSense configuration to revision " . urldecode($_REQUEST['newver']) . ".";
166
				$savemsg .= <<<EOF
167 054f0ed0 Steve Beaver
			<br />
168
		<form action="diag_reboot.php" method="post">
169
			Reboot the firewall to full activate changes?
170 9b83e6fb Viktor G
			<input name="rebootmode" type="hidden" value="Reboot" />
171 054f0ed0 Steve Beaver
			<input name="Submit" type="submit" class="formbtn" value=" Yes " />
172
		</form>
173
EOF;
174 5efa3d45 jim-p
			} else {
175
				$savemsg = "Unable to revert to the selected configuration.";
176
			}
177 054f0ed0 Steve Beaver
		} else {
178 5efa3d45 jim-p
			log_error("There was an error when restoring the AutoConfigBackup item");
179 054f0ed0 Steve Beaver
		}
180 5efa3d45 jim-p
		unlink_if_exists("/tmp/config_restore.xml");
181 054f0ed0 Steve Beaver
	}
182
}
183
184
if ($_REQUEST['download']) {
185
	// Phone home and obtain backups
186
	$curl_session = curl_init();
187
188 f01c0991 Steve Beaver
	curl_setopt($curl_session, CURLOPT_URL, "https://acb.netgate.com/getbkp");
189
	curl_setopt($curl_session, CURLOPT_POSTFIELDS, "userkey=" . $userkey . "&revision=" . urlencode($_REQUEST['download']));
190 054f0ed0 Steve Beaver
	curl_setopt($curl_session, CURLOPT_POST, 3);
191
	curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
192
	curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
193
194 2568e151 Christian McDonald
	curl_setopt($curl_session, CURLOPT_USERAGENT, g_get('product_label') . '/' . rtrim(file_get_contents("/etc/version")));
195 054f0ed0 Steve Beaver
	// Proxy
196 75a3b0de Viktor G
	set_curlproxy($curl_session);
197 054f0ed0 Steve Beaver
	$data = curl_exec($curl_session);
198
199 4174a828 Steve Beaver
	if (curl_errno($curl_session)) {
200
		$fd = fopen("/tmp/acb_backupdebug.txt", "w");
201
		fwrite($fd, "https://acb.netgate.com/getbkp" . "" . "action=sgetbackup" . "\n\n");
202
		fwrite($fd, $data);
203
		fwrite($fd, curl_error($curl_session));
204
		fclose($fd);
205
	} else {
206
		curl_close($curl_session);
207
	}
208
209 054f0ed0 Steve Beaver
	if (!tagfile_deformat($data, $data1, "config.xml")) {
210 f01c0991 Steve Beaver
		$input_errors[] = "The downloaded file does not appear to contain an encrypted pfSense configuration.";
211 054f0ed0 Steve Beaver
	} else {
212
		$ds = explode('++++', $data);
213
		$revision = $_REQUEST['download'];
214
		$sha256sum = $ds[0];
215
		if ($sha256sum == "0") {
216
			$sha256sum = "None on file.";
217
		}
218
		$data = $ds[1];
219
		$configtype = "Encrypted";
220
		if (!tagfile_deformat($data, $data, "config.xml")) {
221
			$input_errors[] = "The downloaded file does not appear to contain an encrypted pfSense configuration.";
222
		}
223
		$data = decrypt_data($data, $decrypt_password);
224
		if (!strstr($data, "pfsense")) {
225
			$data = "Could not decrypt. Different encryption key?";
226 5efa3d45 jim-p
			$input_errors[] = "Could not decrypt config.xml. Check the encryption key and try again.";
227 054f0ed0 Steve Beaver
		}
228
	}
229
}
230
231
// $confvers must be populated viewing info but there were errors
232 bbb3bbeb Viktor G
$confvers = array();
233
if ((!($_REQUEST['download']) || $input_errors) && check_dnsavailable()) {
234 054f0ed0 Steve Beaver
	// Populate available backups
235
	$curl_session = curl_init();
236
237 f01c0991 Steve Beaver
	curl_setopt($curl_session, CURLOPT_URL, "https://acb.netgate.com/list");
238
	curl_setopt($curl_session, CURLOPT_POSTFIELDS, "userkey=" . $userkey .
239
		"&uid=eb6a4e6f76c10734b636" .
240 2568e151 Christian McDonald
		"&version=" . g_get('product_version') .
241 f01c0991 Steve Beaver
		"&uid=" . urlencode($uniqueID));
242 054f0ed0 Steve Beaver
	curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
243
	curl_setopt($curl_session, CURLOPT_POST, 1);
244
	curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
245
246 2568e151 Christian McDonald
	curl_setopt($curl_session, CURLOPT_USERAGENT, g_get('product_label') . '/' . rtrim(file_get_contents("/etc/version")));
247 054f0ed0 Steve Beaver
	// Proxy
248 75a3b0de Viktor G
	set_curlproxy($curl_session);
249 054f0ed0 Steve Beaver
250
	$data = curl_exec($curl_session);
251
252 af0edce6 Steve Beaver
	if (curl_errno($curl_session)) {
253 054f0ed0 Steve Beaver
		$fd = fopen("/tmp/acb_backupdebug.txt", "w");
254 8a6d9d7f Steve Beaver
		fwrite($fd, "https://acb.netgate.com/list" . "" . "action=showbackups" . "\n\n");
255 054f0ed0 Steve Beaver
		fwrite($fd, $data);
256
		fwrite($fd, curl_error($curl_session));
257
		fclose($fd);
258
	} else {
259
		curl_close($curl_session);
260
	}
261
262
	// Loop through and create new confvers
263
	$data_split = explode("\n", $data);
264
265
	foreach ($data_split as $ds) {
266
		$ds_split = explode($exp_sep, $ds);
267
		$tmp_array = array();
268
		$tmp_array['username'] = $ds_split[0];
269
		$tmp_array['reason'] = $ds_split[1];
270
		$tmp_array['time'] = $ds_split[2];
271
272
		/* Convert the time from server time to local. See #5250 */
273
		$budate = new DateTime($tmp_array['time'], $acbtz);
274
		$budate->setTimezone($mytz);
275
		$tmp_array['localtime'] = $budate->format(DATE_RFC2822);
276
277
		if ($ds_split[2] && $ds_split[0]) {
278
			$confvers[] = $tmp_array;
279
		}
280
	}
281
}
282
283
if ($input_errors) {
284
	print_input_errors($input_errors);
285
}
286
if ($savemsg) {
287
	print_info_box($savemsg, 'success');
288
}
289
290
$tab_array = array();
291 587315d5 Steve Beaver
$tab_array[0] = array("Settings", false, "/services_acb_settings.php");
292 054f0ed0 Steve Beaver
if ($_REQUEST['download']) {
293
	$active = false;
294
} else {
295
	$active = true;
296
}
297
298 587315d5 Steve Beaver
$tab_array[1] = array("Restore", $active, "/services_acb.php");
299
300 054f0ed0 Steve Beaver
if ($_REQUEST['download']) {
301 ce77c104 jim-p
	$tab_array[] = array("Revision", true, "/services_acb.php?download=" . htmlspecialchars($_REQUEST['download']));
302 054f0ed0 Steve Beaver
}
303 587315d5 Steve Beaver
304
$tab_array[] = array("Backup now", false, "/services_acb_backup.php");
305 054f0ed0 Steve Beaver
306
display_top_tabs($tab_array);
307
?>
308
309
<div id="loading">
310
	<i class="fa fa-spinner fa-spin"></i> Loading, please wait...
311
</div>
312
313
314
<?php if ($_REQUEST['download'] && (!$input_errors)):
315
316
$form = new Form(false);
317
318
$section = new Form_Section('Backup Details');
319
320
$section->addInput(new Form_Input(
321
	'download',
322
	'Revision date/time',
323
	'text',
324
	$_REQUEST['download']
325
))->setWidth(7)->setReadOnly();
326
327
$section->addInput(new Form_Input(
328
	'reason',
329
	'Revision Reason',
330
	'text',
331
	$_REQUEST['reason']
332
))->setWidth(7)->setReadOnly();
333
334
$section->addInput(new Form_Input(
335
	'shasum',
336
	'SHA256 summary',
337
	'text',
338
	$sha256sum
339
))->setWidth(7)->setReadOnly();
340
341
$section->addInput(new Form_Textarea(
342
	'config_xml',
343
	'Encrypted config.xml',
344
	$ds[1]
345
))->setWidth(7)->setAttribute("rows", "40")->setAttribute("wrap", "off");
346
347
$section->addInput(new Form_Textarea(
348
	'dec_config_xml',
349
	'Decrypted config.xml',
350
	$data
351
))->setWidth(7)->setAttribute("rows", "40")->setAttribute("wrap", "off");
352
353
$form->add($section);
354
355
print($form);
356
357
?>
358 587315d5 Steve Beaver
<a class="btn btn-primary" title="<?=gettext('Restore this revision')?>" href="services_acb.php?newver=<?= urlencode($_REQUEST['download']) ?>" onclick="return confirm('<?=gettext("Are you sure you want to restore {$cv['localtime']}?")?>')"><i class="fa fa-undo"></i> Install this revision</a>
359 054f0ed0 Steve Beaver
360
<?php else:
361
362 f01c0991 Steve Beaver
$section2 = new Form_Section('Device key');
363
$group = new Form_Group("Device key");
364
365
$group->add(new Form_Input(
366
	'devkey',
367
	'Device key',
368
	'text',
369
	$userkey
370
))->setWidth(7)->setHelp("ID used to identify this firewall (derived from the SSH public key.) " .
371
	"See help below for more details. %sPlease make a safe copy of this ID value.%s If it is lost, your backups will" .
372
	" be lost too!", "<strong>", "</strong>");
373
374
$group->add(new Form_Button(
375
	'upduserkey',
376
	'Submit',
377
	null,
378
	'fa-save'
379
))->addClass('btn-success btn-xs');
380
381
$group->add(new Form_Button(
382
	'restore',
383
	'Reset',
384
	null,
385
	'fa-refresh'
386
))->addClass('btn-info btn-xs');
387
388
$section2->add($group);
389
print($section2);
390
391
print('<div class="infoblock">');
392
print_info_box(gettext("The Device key listed above is derived from the SSH public key of the firewall. When a configuration is saved, it is identified by this value." .
393
	" If you are restoring the configuration of another firewall, paste the Device key from that firewall into the Device ID field above and click \"Submit\"." .
394
	" This will temporarily override the ID for this session."), 'info', false);
395
print('</div>');
396 f0fdd1ab Steve Beaver
397 054f0ed0 Steve Beaver
?>
398
<div class="panel panel-default">
399
	<div class="panel-heading"><h2 class="panel-title"><?=gettext("Automatic Configuration Backups")?></h2></div>
400
	<div class="panel-body">
401
		<div class="table-responsive">
402
		</div>
403
		<div class="table-responsive">
404 21cd4a8b Viktor G
			<table class="table table-striped table-hover table-condensed sortable-theme-bootstrap" id="backups" data-sortable>
405 054f0ed0 Steve Beaver
				<thead>
406
					<tr>
407 21cd4a8b Viktor G
						<th data-sortable-type="date" width="30%"><?=gettext("Date")?></th>
408 054f0ed0 Steve Beaver
						<th width="60%"><?=gettext("Configuration Change")?></th>
409
						<th width="10%"><?=gettext("Actions")?></th>
410
					</tr>
411
				</thead>
412
				<tbody>
413
414
			<?php
415
				$counter = 0;
416 404efa21 jim-p
				if (config_get_path('system/acb/reverse') == "yes"){
417 3f8e09a5 Christopher
					$confvers = array_reverse($confvers);
418
				}
419
420 054f0ed0 Steve Beaver
				foreach ($confvers as $cv):
421
			?>
422
					<tr>
423
						<td><?= $cv['localtime']; ?></td>
424
						<td><?= $cv['reason']; ?></td>
425
						<td>
426 f01c0991 Steve Beaver
							<a class="fa fa-undo"		title="<?=gettext('Restore this revision')?>"	href="services_acb.php?hostname=<?=urlencode($hostname)?>&userkey=<?=urlencode($userkey)?>&newver=<?=urlencode($cv['time'])?>"	onclick="return confirm('<?=gettext("Are you sure you want to restore {$cv['localtime']}?")?>')"></a>
427
							<a class="fa fa-download"	title="<?=gettext('Show info')?>"	href="services_acb.php?download=<?=urlencode($cv['time'])?>&hostname=<?=urlencode($hostname)?>&userkey=<?=urlencode($userkey)?>&reason=<?=urlencode($cv['reason'])?>"></a>
428 3fd4f32c Steve Beaver
<?php
429
		if ($userkey == $origkey) {
430
?>
431 f01c0991 Steve Beaver
							<a class="fa fa-trash"		title="<?=gettext('Delete config')?>"	href="services_acb.php?hostname=<?=urlencode($hostname)?>&rmver=<?=urlencode($cv['time'])?>"></a>
432 3fd4f32c Steve Beaver
<?php 	} ?>
433 054f0ed0 Steve Beaver
						</td>
434
					</tr>
435
				<?php	$counter++;
436
				endforeach;
437 21cd4a8b Viktor G
				?>
438 054f0ed0 Steve Beaver
				</tbody>
439
			</table>
440 21cd4a8b Viktor G
			<table class="table table-striped table-hover table-condensed" id="backups" data-sortable>
441
			<?php if ($counter == 0): ?>
442
				<tr>
443
					<td colspan="3" align="center" class="text-danger"><strong>
444
						<?=gettext("No backups could be located for this device.")?>
445
						</strong>
446
					</td>
447
				</tr>
448
			<?php else: ?>
449
				<tr>
450
					<td colspan="3" align="center">
451
						<br /><?=gettext("Current count of hosted backups")?> : <?= $counter ?>
452
					</td>
453
				</tr>
454
			<?php endif; ?>
455
			</table>
456 054f0ed0 Steve Beaver
		</div>
457
	</div>
458
</div>
459
<?php
460
461
endif; ?>
462
463
</form>
464
465
<script type="text/javascript">
466
//<![CDATA[
467
events.push(function(){
468
	$('#loading').hide();
469
470
	// On clicking Submit", reload the page but with a POST parameter "userkey" set
471
	$('#upduserkey').click(function() {
472
		var $form = $('<form>');
473
		var newuserkey = $('#devkey').val();
474
475
		$form
476
			.attr("method", "POST")
477 587315d5 Steve Beaver
			.attr("action", '/services_acb.php')
478 054f0ed0 Steve Beaver
			// The CSRF magic is required because we will be viewing the results of the POST
479
			.append(
480
				$("<input>")
481
					.attr("type", "hidden")
482
					.attr("name", "__csrf_magic")
483
					.val(csrfMagicToken)
484
			)
485
			.append(
486
			$("<input>")
487
				.attr("type", "hidden")
488
				.attr("name", "userkey")
489
				.val(newuserkey)
490
			)
491
			.appendTo('body')
492
			.submit();
493
	});
494
495
	$('#restore').click(function() {
496
		$('#devkey').val("<?=$origkey?>");
497
	});
498
});
499
//]]>
500
</script>
501
502
<?php include("foot.inc"); ?>