Project

General

Profile

Download (11.4 KB) Statistics
| Branch: | Tag: | Revision:
1 054f0ed0 Steve Beaver
<?php
2
/*
3
 * autoconfigbackup.inc
4
 *
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 8f2f85c3 Luiz Otavio O Souza
 * Copyright (c) 2014-2022 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
24
require_once("filter.inc");
25
require_once("notices.inc");
26
27
// If there is no ssh key in the system to identify this firewall, generate a pair now
28
function get_device_key() {
29
	if (!file_exists("/etc/ssh/ssh_host_ed25519_key.pub")) {
30 c1f0a583 Steve Beaver
		// Remove any possible matching key so we don't get an overwrite prompt
31
		if (file_exists('/etc/ssh/ssh_host_ed25519_key')) {
32
			unlink('/etc/ssh/ssh_host_ed25519_key');
33
		}
34
35
		// Generate a new key pair
36 8411851a Steve Beaver
		exec("/usr/bin/nice -n20 /usr/bin/ssh-keygen -t ed25519 -b 4096 -N '' -f /etc/ssh/ssh_host_ed25519_key");
37 c1f0a583 Steve Beaver
		sleep(2);
38
39
		$cnt = 0;
40
		while(!file_exists("/etc/ssh/ssh_host_ed25519_key.pub")) {
41
			sleep(2);
42
			if (++$cnt > 10) {
43
				return "";
44
			}
45
		}
46
	}
47
48
	$pkey =  file_get_contents("/etc/ssh/ssh_host_ed25519_key.pub");
49
50
	// Check that the key looks reasonable
51 8411851a Steve Beaver
	if (substr($pkey, 0, 3) != "ssh") {
52 c1f0a583 Steve Beaver
		return "";
53 054f0ed0 Steve Beaver
	}
54
55 c1f0a583 Steve Beaver
	return hash("sha256", $pkey);
56 054f0ed0 Steve Beaver
}
57
58
$origkey = get_device_key();
59
60
if (isset($_REQUEST['userkey']) && !empty($_REQUEST['userkey'])) {
61
	$userkey = htmlentities($_REQUEST['userkey']);
62
} else {
63
	$userkey = get_device_key();
64
}
65
66
$uniqueID = system_get_uniqueid();
67
68
/* Check whether ACB is enabled */
69
function acb_enabled() {
70
	global $config;
71
	$acb_enabled = false;
72
73
	if (is_array($config['system']['acb'])) {
74
		if ($config['system']['acb']['enable'] == "yes") {
75
			$acb_enabled = true;
76
		}
77
	}
78
79
	return $acb_enabled;
80
}
81
82
// Ensures patches match
83
function acb_custom_php_validation_command($post, &$input_errors) {
84
	global $_POST, $savemsg, $config;
85
86
	// Do nothing when ACB is disabled in configuration
87
	// This also makes it possible to delete the credentials from config.xml
88
	if (!acb_enabled()) {
89
		// We do not need to store this value.
90
		unset($_POST['testconnection']);
91
		return;
92
	}
93
94
	if (!$post['crypto_password'] or !$post['crypto_password2']) {
95
		$input_errors[] = "The encryption password is required.";
96
	}
97
98
	if ($post['crypto_password'] <> $post['crypto_password2']) {
99
		$input_errors[] = "Sorry, the entered encryption passwords do not match.";
100
	}
101
102
	if ($post['testconnection']) {
103
		$status = test_connection($post);
104
		if ($status) {
105
			$savemsg = "Connection to the ACB server was tested with no errors.";
106
		}
107
	}
108
109
	// We do not need to store this value.
110
	unset($_POST['testconnection']);
111
}
112
113
function acb_custom_php_resync_config_command() {
114
	// Do nothing when ACB is disabled in configuration
115
	if (!acb_enabled()) {
116
		return;
117
	}
118
119 522388a7 Renato Botelho
	unlink_if_exists("/cf/conf/lastpfSbackup.txt");
120 af0edce6 Steve Beaver
121 054f0ed0 Steve Beaver
	if (!function_exists("filter_configure")) {
122
		require_once("filter.inc");
123
	}
124 af0edce6 Steve Beaver
125 054f0ed0 Steve Beaver
	filter_configure();
126 af0edce6 Steve Beaver
127 054f0ed0 Steve Beaver
	if ($savemsg) {
128
		$savemsg .= "<br/>";
129
	}
130 af0edce6 Steve Beaver
131 054f0ed0 Steve Beaver
	$savemsg .= "A configuration backup has been queued.";
132
}
133
134
function test_connection($post) {
135 8a6d9d7f Steve Beaver
	global $savemsg, $config, $g;
136 054f0ed0 Steve Beaver
137
	// Do nothing when booting or when not enabled
138
	if (platform_booting() || !acb_enabled()) {
139
		return;
140
	}
141
142 f3f98e97 Phil Davis
	// Separator used during client / server communications
143 054f0ed0 Steve Beaver
	$oper_sep = "\|\|";
144
145
	// Encryption password
146
	$decrypt_password = $post['crypto_password'];
147
148
	// Defined username. Username must be sent lowercase. See Redmine #7127 and Netgate Redmine #163
149
	$username = strtolower($post['username']);
150
151
	// Defined password
152
	$password = $post['password'];
153
154
	// Set hostname
155
	$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
156
157
	// URL to restore.php
158 8a6d9d7f Steve Beaver
	$get_url = "https://acb.netgate.com/getbkp";
159 054f0ed0 Steve Beaver
160
	// Populate available backups
161
	$curl_session = curl_init();
162
	curl_setopt($curl_session, CURLOPT_URL, $get_url);
163
	curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
164
	curl_setopt($curl_session, CURLOPT_POST, 1);
165
	curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
166
	curl_setopt($curl_session, CURLOPT_CONNECTTIMEOUT, 55);
167
	curl_setopt($curl_session, CURLOPT_TIMEOUT, 30);
168 573ec19d Renato Botelho do Couto
	curl_setopt($curl_session, CURLOPT_USERAGENT, $g['product_label'] . '/' . rtrim(file_get_contents("/etc/version")));
169 054f0ed0 Steve Beaver
	// Proxy
170 8b424bca Viktor G
	set_curlproxy($curl_session);
171 054f0ed0 Steve Beaver
172
	curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=showbackups&hostname={$hostname}");
173
	$data = curl_exec($curl_session);
174
175
	if (curl_errno($curl_session)) {
176
		return("An error occurred " . curl_error($curl_session));
177
	} else {
178
		curl_close($curl_session);
179
	}
180
181
	return;
182
}
183
184 463d5d11 Steve Beaver
function upload_config($manual = false) {
185 054f0ed0 Steve Beaver
	global $config, $g, $input_errors, $userkey, $uniqueID;
186
187
	if (empty($userkey)) {
188
		$userkey = get_device_key();
189
	}
190
191
	if (empty($uniqueID)) {
192
		$uniqueID = system_get_uniqueid();
193
	}
194
195
	// Do nothing when booting or when not enabled
196
	if (platform_booting() || !acb_enabled()) {
197
		return;
198
	}
199
200
	/*
201 8a6d9d7f Steve Beaver
	 * pfSense upload config to acb.netgate.com script
202 054f0ed0 Steve Beaver
	 * This file plugs into config.inc (/usr/local/pkg/parse_config)
203
	 * and runs every time the running firewall filter changes.
204
	 *
205
	 */
206
207
	if (file_exists("/tmp/acb_nooverwrite")) {
208
		unlink("/tmp/acb_nooverwrite");
209
		$nooverwrite = "true";
210
	} else {
211
		$nooverwrite = "false";
212
	}
213
214
	// Define some needed variables
215
	if (file_exists("/cf/conf/lastpfSbackup.txt")) {
216
		$last_backup_date = str_replace("\n", "", file_get_contents("/cf/conf/lastpfSbackup.txt"));
217
	} else {
218
		$last_backup_date = "";
219
	}
220
221
	$last_config_change = $config['revision']['time'];
222
	$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
223 6f6299a3 Steve Beaver
	$reason	= $config['revision']['description'];
224 af0edce6 Steve Beaver
225 6f6299a3 Steve Beaver
	if ($manual && array_key_exists('numman', $config['system']['acb'])) {
226
		$manmax = $config['system']['acb']['numman'];
227 054f0ed0 Steve Beaver
	} else {
228 6f6299a3 Steve Beaver
		$manmax = "0";
229 054f0ed0 Steve Beaver
	}
230
231 587315d5 Steve Beaver
	$encryptpw = $config['system']['acb']['encryption_password'];
232 054f0ed0 Steve Beaver
233
	// Define upload_url, must be present after other variable definitions due to username, password
234
	$upload_url = "https://acb.netgate.com/save";
235
236
	if (!$encryptpw) {
237
		if (!file_exists("/cf/conf/autoconfigback.notice")) {
238
			$notice_text = "The encryption password is not set for Automatic Configuration Backup.";
239 587315d5 Steve Beaver
			$notice_text .= " Please correct this in Services -> AutoConfigBackup -> Settings.";
240 ce9eb0fb Steve Beaver
			log_error($notice_text);
241
			file_notice("AutoConfigBackup", $notice_text, $notice_text, "");
242 054f0ed0 Steve Beaver
			touch("/cf/conf/autoconfigback.notice");
243
		}
244
	} else {
245
		/* If configuration has changed, upload to pfS */
246
		if ($last_backup_date <> $last_config_change) {
247
248 d86a9bf9 jim-p
			$notice_text = "Beginning configuration backup to " . $upload_url;
249 054f0ed0 Steve Beaver
			log_error($notice_text);
250
			update_filter_reload_status($notice_text);
251
252
			// Encrypt config.xml
253
			$data = file_get_contents("/cf/conf/config.xml");
254
			$raw_config_sha256_hash = trim(shell_exec("/sbin/sha256 /cf/conf/config.xml | /usr/bin/awk '{ print $4 }'"));
255
			$data = encrypt_data($data, $encryptpw);
256
			$tmpname = "/tmp/" . $raw_config_sha256_hash . ".tmp";
257
			tagfile_reformat($data, $data, "config.xml");
258
			file_put_contents($tmpname, $data);
259
260
			$post_fields = array(
261
				'reason' => htmlspecialchars($reason),
262
				'uid' => $uniqueID,
263
				'file' => curl_file_create($tmpname, 'image/jpg', 'config.jpg'),
264
				'userkey' => htmlspecialchars($userkey),
265
				'sha256_hash' => $raw_config_sha256_hash,
266
				'version' => $g['product_version'],
267 6f6299a3 Steve Beaver
				'hint' => $config['system']['acb']['hint'],
268
				'manmax' => $manmax
269 054f0ed0 Steve Beaver
			);
270
271 17490b15 Viktor G
			unlink_if_exists($tmpname);
272
273 5ae46c60 Steve Beaver
			if (!is_dir($g['acbbackuppath'])) {
274
				mkdir($g['acbbackuppath']);
275
			}
276
277
			file_put_contents($g['acbbackuppath'] . $post_fields['sha256_hash'] . ".form", json_encode($post_fields));
278
			file_put_contents($g['acbbackuppath'] . $post_fields['sha256_hash'] . ".data", $data);
279
280
			/*
281
			This functionality is now provided by a cron job /usr/local/sbin/acbupload.php run once per minute when ACB is enabled.
282
			Commented block can be removed after testing.
283
284 054f0ed0 Steve Beaver
			// Check configuration into the ESF repo
285
			$curl_session = curl_init();
286
287
			curl_setopt($curl_session, CURLOPT_URL, "https://acb.netgate.com/save");
288
			curl_setopt($curl_session, CURLOPT_POST, count($post_fields));
289
			curl_setopt($curl_session, CURLOPT_POSTFIELDS, $post_fields);
290
			curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
291 ce9eb0fb Steve Beaver
			curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
292 054f0ed0 Steve Beaver
			curl_setopt($curl_session, CURLOPT_CONNECTTIMEOUT, 55);
293
			curl_setopt($curl_session, CURLOPT_TIMEOUT, 30);
294 573ec19d Renato Botelho do Couto
			curl_setopt($curl_session, CURLOPT_USERAGENT, $g['product_label'] . '/' . rtrim(file_get_contents("/etc/version")));
295 054f0ed0 Steve Beaver
			// Proxy
296 8b424bca Viktor G
			set_curlproxy($curl_session);
297 054f0ed0 Steve Beaver
298
			$data = curl_exec($curl_session);
299
300 c3c79c8b Renato Botelho
			unlink_if_exists($tmpname);
301 054f0ed0 Steve Beaver
302
			if (curl_errno($curl_session)) {
303
				$fd = fopen("/tmp/backupdebug.txt", "w");
304
				fwrite($fd, $upload_url . "" . $fields_string . "\n\n");
305
				fwrite($fd, $data);
306
				fwrite($fd, curl_error($curl_session));
307
				fclose($fd);
308
			} else {
309
				curl_close($curl_session);
310
			}
311
312
			if (strpos($data, "500") != false) {
313 573ec19d Renato Botelho do Couto
				$notice_text = sprintf(gettext(
314
				    "An error occurred while uploading your %s configuration to "), $g['product_label']) .
315
				    $upload_url . " (" . htmlspecialchars($data) . ")";
316 054f0ed0 Steve Beaver
				log_error($notice_text . " - " . $data);
317 ce9eb0fb Steve Beaver
				file_notice("AutoConfigBackup", $notice_text);
318 054f0ed0 Steve Beaver
				update_filter_reload_status($notice_text);
319
				$input_errors["acb_upload"] = $notice_text;
320
			} else {
321
				// Update last pfS backup time
322
				$fd = fopen("/cf/conf/lastpfSbackup.txt", "w");
323
				fwrite($fd, $config['revision']['time']);
324
				fclose($fd);
325
				$notice_text = "End of configuration backup to " . $upload_url . " (success).";
326
				log_error($notice_text);
327
				update_filter_reload_status($notice_text);
328
			}
329 5ae46c60 Steve Beaver
*/
330 054f0ed0 Steve Beaver
		} else {
331
			// Debugging
332 8a6d9d7f Steve Beaver
			//log_error("No https://acb.netgate.com backup required.");
333 054f0ed0 Steve Beaver
		}
334
	}
335
}
336 55cbdcb0 Steve Beaver
337
// Save the updated ACB configuration
338
// Create a crontab entry for scheduled backups
339
// if frequency == "cron", a new crontab entry is created, otherwise any existing
340
// ACB entry is removed
341 3f8e09a5 Christopher
function setup_ACB($enable, $hint, $frequency, $minute, $hours, $month, $day, $dow, $numman, $reverse, $pwd) {
342 55cbdcb0 Steve Beaver
	global $config;
343
344 868c1a67 Steve Beaver
	init_config_arr(array('system', 'acb'));
345
346 5ae46c60 Steve Beaver
	// Randomize the minutes if not specified
347 e4a2bd9b Steve Beaver
	if (!isset($minute) || strlen($minute) == 0 || $minute == "0") {
348 5ae46c60 Steve Beaver
		$minute = rand(1, 59);
349
	}
350
351 55cbdcb0 Steve Beaver
	$config['system']['acb']['enable'] = $enable;
352
	$config['system']['acb']['hint'] = $hint;
353
	$config['system']['acb']['frequency'] = $frequency;
354 25e8eb57 Viktor G
	$config['system']['acb']['minute'] = $minute;
355 55cbdcb0 Steve Beaver
	$config['system']['acb']['hour'] = $hours;
356
	$config['system']['acb']['month'] = $month;
357
	$config['system']['acb']['day'] = $day;
358
	$config['system']['acb']['dow'] = $dow;
359
	$config['system']['acb']['numman'] = $numman;
360 3f8e09a5 Christopher
	$config['system']['acb']['reverse'] = $reverse;
361 f1c8242d Steve Beaver
	if (strlen($pwd) >= 8) {
362
		$config['system']['acb']['encryption_password'] = $pwd;
363
	}
364
365 5ae46c60 Steve Beaver
	install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php /usr/local/sbin/execacb.php", $frequency == "cron",
366
	   $minute,
367
	   is_numeric($hours) ? $hours : "*",
368
	   is_numeric($day) ? $day : "*",
369
	   is_numeric($month) ? $month : "*",
370
	   is_numeric($dow) ? $dow : "*"
371
	);
372 55cbdcb0 Steve Beaver
373 5ae46c60 Steve Beaver
	// Install cron job 
374
	install_cron_job("/usr/bin/nice -n20 /usr/local/bin/php /usr/local/sbin/acbupload.php", $enable == "yes", "*");
375 55cbdcb0 Steve Beaver
376
	write_config("AutoConfigBackup settings updated");
377 5ae46c60 Steve Beaver
378
	return($config['system']['acb']);
379 55cbdcb0 Steve Beaver
}