Project

General

Profile

Download (9.62 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * autoconfigbackup.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2008-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2020 Rubicon Communications, LLC (Netgate)
9
 * 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
		exec("/usr/bin/nice -n20 /usr/bin/ssh-keygen -t ed25519 -b 4096 -N '' -f /etc/ssh//ssh_host_ed25519_key");
31
	}
32

    
33
	// The userkey (firewall identifier) is an sha256 hash of the ed25519 public key
34
	return hash("sha256", file_get_contents("/etc/ssh/ssh_host_ed25519_key.pub"));
35
}
36

    
37
$origkey = get_device_key();
38

    
39
if (isset($_REQUEST['userkey']) && !empty($_REQUEST['userkey'])) {
40
	$userkey = htmlentities($_REQUEST['userkey']);
41
} else {
42
	$userkey = get_device_key();
43
}
44

    
45
$uniqueID = system_get_uniqueid();
46

    
47
/* Check whether ACB is enabled */
48
function acb_enabled() {
49
	global $config;
50
	$acb_enabled = false;
51

    
52
	if (is_array($config['system']['acb'])) {
53
		if ($config['system']['acb']['enable'] == "yes") {
54
			$acb_enabled = true;
55
		}
56
	}
57

    
58
	return $acb_enabled;
59
}
60

    
61
// Ensures patches match
62
function acb_custom_php_validation_command($post, &$input_errors) {
63
	global $_POST, $savemsg, $config;
64

    
65
	// Do nothing when ACB is disabled in configuration
66
	// This also makes it possible to delete the credentials from config.xml
67
	if (!acb_enabled()) {
68
		// We do not need to store this value.
69
		unset($_POST['testconnection']);
70
		return;
71
	}
72

    
73
	if (!$post['crypto_password'] or !$post['crypto_password2']) {
74
		$input_errors[] = "The encryption password is required.";
75
	}
76

    
77
	if ($post['crypto_password'] <> $post['crypto_password2']) {
78
		$input_errors[] = "Sorry, the entered encryption passwords do not match.";
79
	}
80

    
81
	if ($post['testconnection']) {
82
		$status = test_connection($post);
83
		if ($status) {
84
			$savemsg = "Connection to the ACB server was tested with no errors.";
85
		}
86
	}
87

    
88
	// We do not need to store this value.
89
	unset($_POST['testconnection']);
90
}
91

    
92
function acb_custom_php_resync_config_command() {
93
	// Do nothing when ACB is disabled in configuration
94
	if (!acb_enabled()) {
95
		return;
96
	}
97

    
98
	unlink_if_exists("/cf/conf/lastpfSbackup.txt");
99

    
100
	if (!function_exists("filter_configure")) {
101
		require_once("filter.inc");
102
	}
103

    
104
	filter_configure();
105

    
106
	if ($savemsg) {
107
		$savemsg .= "<br/>";
108
	}
109

    
110
	$savemsg .= "A configuration backup has been queued.";
111
}
112

    
113
function configure_proxy() {
114
	global $config;
115
	$ret = array();
116
	if (!empty($config['system']['proxyurl'])) {
117
		$ret[CURLOPT_PROXY] = $config['system']['proxyurl'];
118
		if (!empty($config['system']['proxyport'])) {
119
			$ret[CURLOPT_PROXYPORT] = $config['system']['proxyport'];
120
		}
121
		if (!empty($config['system']['proxyuser']) && !empty($config['system']['proxypass'])) {
122
			$ret[CURLOPT_PROXYAUTH] = CURLAUTH_ANY | CURLAUTH_ANYSAFE;
123
			$ret[CURLOPT_PROXYUSERPWD] = "{$config['system']['proxyuser']}:{$config['system']['proxypass']}";
124
		}
125
	}
126
	return $ret;
127
}
128

    
129
function test_connection($post) {
130
	global $savemsg, $config, $g;
131

    
132
	// Do nothing when booting or when not enabled
133
	if (platform_booting() || !acb_enabled()) {
134
		return;
135
	}
136

    
137
	// Separator used during client / server communications
138
	$oper_sep = "\|\|";
139

    
140
	// Encryption password
141
	$decrypt_password = $post['crypto_password'];
142

    
143
	// Defined username. Username must be sent lowercase. See Redmine #7127 and Netgate Redmine #163
144
	$username = strtolower($post['username']);
145

    
146
	// Defined password
147
	$password = $post['password'];
148

    
149
	// Set hostname
150
	$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
151

    
152
	// URL to restore.php
153
	$get_url = "https://acb.netgate.com/getbkp";
154

    
155
	// Populate available backups
156
	$curl_session = curl_init();
157
	curl_setopt($curl_session, CURLOPT_URL, $get_url);
158
	curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
159
	curl_setopt($curl_session, CURLOPT_POST, 1);
160
	curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
161
	curl_setopt($curl_session, CURLOPT_CONNECTTIMEOUT, 55);
162
	curl_setopt($curl_session, CURLOPT_TIMEOUT, 30);
163
	curl_setopt($curl_session, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
164
	// Proxy
165
	curl_setopt_array($curl_session, configure_proxy());
166

    
167
	curl_setopt($curl_session, CURLOPT_POSTFIELDS, "action=showbackups&hostname={$hostname}");
168
	$data = curl_exec($curl_session);
169

    
170
	if (curl_errno($curl_session)) {
171
		return("An error occurred " . curl_error($curl_session));
172
	} else {
173
		curl_close($curl_session);
174
	}
175

    
176
	return;
177
}
178

    
179
function upload_config($manual = false) {
180
	global $config, $g, $input_errors, $userkey, $uniqueID;
181

    
182
	if (empty($userkey)) {
183
		$userkey = get_device_key();
184
	}
185

    
186
	if (empty($uniqueID)) {
187
		$uniqueID = system_get_uniqueid();
188
	}
189

    
190
	// Do nothing when booting or when not enabled
191
	if (platform_booting() || !acb_enabled()) {
192
		return;
193
	}
194

    
195
	/*
196
	 * pfSense upload config to acb.netgate.com script
197
	 * This file plugs into config.inc (/usr/local/pkg/parse_config)
198
	 * and runs every time the running firewall filter changes.
199
	 *
200
	 */
201

    
202
	if (file_exists("/tmp/acb_nooverwrite")) {
203
		unlink("/tmp/acb_nooverwrite");
204
		$nooverwrite = "true";
205
	} else {
206
		$nooverwrite = "false";
207
	}
208

    
209
	// Define some needed variables
210
	if (file_exists("/cf/conf/lastpfSbackup.txt")) {
211
		$last_backup_date = str_replace("\n", "", file_get_contents("/cf/conf/lastpfSbackup.txt"));
212
	} else {
213
		$last_backup_date = "";
214
	}
215

    
216
	$last_config_change = $config['revision']['time'];
217
	$hostname = $config['system']['hostname'] . "." . $config['system']['domain'];
218
	$reason	= $config['revision']['description'];
219

    
220
	if ($manual && array_key_exists('numman', $config['system']['acb'])) {
221
		$manmax = $config['system']['acb']['numman'];
222
	} else {
223
		$manmax = "0";
224
	}
225

    
226
	$encryptpw = $config['system']['acb']['encryption_password'];
227

    
228
	// Define upload_url, must be present after other variable definitions due to username, password
229
	$upload_url = "https://acb.netgate.com/save";
230

    
231
	if (!$encryptpw) {
232
		if (!file_exists("/cf/conf/autoconfigback.notice")) {
233
			$notice_text = "The encryption password is not set for Automatic Configuration Backup.";
234
			$notice_text .= " Please correct this in Services -> AutoConfigBackup -> Settings.";
235
			log_error($notice_text);
236
			file_notice("AutoConfigBackup", $notice_text, $notice_text, "");
237
			touch("/cf/conf/autoconfigback.notice");
238
		}
239
	} else {
240
		/* If configuration has changed, upload to pfS */
241
		if ($last_backup_date <> $last_config_change) {
242

    
243
			$notice_text = "Beginning configuration backup to " . $upload_url;
244
			log_error($notice_text);
245
			update_filter_reload_status($notice_text);
246

    
247
			// Encrypt config.xml
248
			$data = file_get_contents("/cf/conf/config.xml");
249
			$raw_config_sha256_hash = trim(shell_exec("/sbin/sha256 /cf/conf/config.xml | /usr/bin/awk '{ print $4 }'"));
250
			$data = encrypt_data($data, $encryptpw);
251
			$tmpname = "/tmp/" . $raw_config_sha256_hash . ".tmp";
252
			tagfile_reformat($data, $data, "config.xml");
253
			file_put_contents($tmpname, $data);
254

    
255
			$post_fields = array(
256
				'reason' => htmlspecialchars($reason),
257
				'uid' => $uniqueID,
258
				'file' => curl_file_create($tmpname, 'image/jpg', 'config.jpg'),
259
				'userkey' => htmlspecialchars($userkey),
260
				'sha256_hash' => $raw_config_sha256_hash,
261
				'version' => $g['product_version'],
262
				'hint' => $config['system']['acb']['hint'],
263
				'manmax' => $manmax
264
			);
265

    
266
			// Check configuration into the ESF repo
267
			$curl_session = curl_init();
268

    
269
			curl_setopt($curl_session, CURLOPT_URL, "https://acb.netgate.com/save");
270
			curl_setopt($curl_session, CURLOPT_POST, count($post_fields));
271
			curl_setopt($curl_session, CURLOPT_POSTFIELDS, $post_fields);
272
			curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, 1);
273
			curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, 1);
274
			curl_setopt($curl_session, CURLOPT_CONNECTTIMEOUT, 55);
275
			curl_setopt($curl_session, CURLOPT_TIMEOUT, 30);
276
			curl_setopt($curl_session, CURLOPT_USERAGENT, $g['product_name'] . '/' . rtrim(file_get_contents("/etc/version")));
277
			// Proxy
278
			curl_setopt_array($curl_session, configure_proxy());
279

    
280
			$data = curl_exec($curl_session);
281

    
282
			unlink_if_exists($tmpname);
283

    
284
			if (curl_errno($curl_session)) {
285
				$fd = fopen("/tmp/backupdebug.txt", "w");
286
				fwrite($fd, $upload_url . "" . $fields_string . "\n\n");
287
				fwrite($fd, $data);
288
				fwrite($fd, curl_error($curl_session));
289
				fclose($fd);
290
			} else {
291
				curl_close($curl_session);
292
			}
293

    
294
			if (strpos($data, "500") != false) {
295
				$notice_text = gettext("An error occurred while uploading your pfSense configuration to ") . $upload_url . " (" . htmlspecialchars($data) . ")";
296
				log_error($notice_text . " - " . $data);
297
				file_notice("AutoConfigBackup", $notice_text);
298
				update_filter_reload_status($notice_text);
299
				$input_errors["acb_upload"] = $notice_text;
300
			} else {
301
				// Update last pfS backup time
302
				$fd = fopen("/cf/conf/lastpfSbackup.txt", "w");
303
				fwrite($fd, $config['revision']['time']);
304
				fclose($fd);
305
				$notice_text = "End of configuration backup to " . $upload_url . " (success).";
306
				log_error($notice_text);
307
				update_filter_reload_status($notice_text);
308
			}
309

    
310
		} else {
311
			// Debugging
312
			//log_error("No https://acb.netgate.com backup required.");
313
		}
314
	}
315
}
(1-1/60)