Project

General

Profile

Download (37.3 KB) Statistics
| Branch: | Tag: | Revision:
1 12df7edc Erik
<?php
2 09221bc3 Renato Botelho
/*
3 ac24dc24 Renato Botelho
 * config.lib.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6 38809d47 Renato Botelho do Couto
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8 402c98a2 Reid Linnemann
 * Copyright (c) 2014-2023 Rubicon Communications, LLC (Netgate)
9 ac24dc24 Renato Botelho
 * Copyright (c) 2009 Erik Kristensen
10
 * All rights reserved.
11
 *
12
 * originally part of m0n0wall (http://m0n0.ch/wall)
13 c5d81585 Renato Botelho
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
14 ac24dc24 Renato Botelho
 * All rights reserved.
15
 *
16 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
17
 * you may not use this file except in compliance with the License.
18
 * You may obtain a copy of the License at
19 ac24dc24 Renato Botelho
 *
20 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
21 ac24dc24 Renato Botelho
 *
22 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
23
 * distributed under the License is distributed on an "AS IS" BASIS,
24
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
 * See the License for the specific language governing permissions and
26
 * limitations under the License.
27 ac24dc24 Renato Botelho
 */
28 12df7edc Erik
29 fab98cb6 Reid Linnemann
require_once('util.inc');
30
31 12df7edc Erik
/****f* config/encrypted_configxml
32
 * NAME
33
 *   encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock.
34
 * INPUTS
35
 *   None
36
 * RESULT
37
 *   $config 	- rewrites config.xml without encryption
38
 ******/
39
function encrypted_configxml() {
40
	global $g, $config;
41 02e9880e Ermal
42 2568e151 Christian McDonald
	if (!file_exists(g_get('conf_path') . "/config.xml")) {
43 02e9880e Ermal
		return;
44 1e0b1727 Phil Davis
	}
45 02e9880e Ermal
46 1e0b1727 Phil Davis
	if (!platform_booting()) {
47 02e9880e Ermal
		return;
48 1e0b1727 Phil Davis
	}
49 02e9880e Ermal
50 2568e151 Christian McDonald
	$configtxt = file_get_contents(g_get('conf_path') . "/config.xml");
51 1e0b1727 Phil Davis
	if (tagfile_deformat($configtxt, $configtxt, "config.xml")) {
52 02e9880e Ermal
		$fp = fopen('php://stdin', 'r');
53
		$data = "";
54
		echo "\n\n*** Encrypted config.xml detected ***\n";
55 1e0b1727 Phil Davis
		while ($data == "") {
56 02e9880e Ermal
			echo "\nEnter the password to decrypt config.xml: ";
57
			$decrypt_password = chop(fgets($fp));
58
			$data = decrypt_data($configtxt, $decrypt_password);
59 1e0b1727 Phil Davis
			if (!strstr($data, "<pfsense>")) {
60 12df7edc Erik
				$data = "";
61 1e0b1727 Phil Davis
			}
62
			if ($data) {
63 2568e151 Christian McDonald
				$fd = fopen(g_get('conf_path') . "/config.xml.tmp", "w");
64 02e9880e Ermal
				fwrite($fd, $data);
65
				fclose($fd);
66
				exec("/bin/mv {$g['conf_path']}/config.xml.tmp {$g['conf_path']}/config.xml");
67 9d3d8d00 Vinicius Coque
				echo "\n" . gettext("Config.xml unlocked.") . "\n";
68 02e9880e Ermal
				fclose($fp);
69 c5663bf5 Renato Botelho
				//pfSense_fsync("{$g['conf_path']}/config.xml");
70 02e9880e Ermal
			} else {
71 9d3d8d00 Vinicius Coque
				echo "\n" . gettext("Invalid password entered.  Please try again.") . "\n";
72 12df7edc Erik
			}
73
		}
74
	}
75
}
76
77
/****f* config/parse_config
78
 * NAME
79
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
80
 * INPUTS
81
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
82
 * RESULT
83
 *   $config      - array containing all configuration variables
84
 ******/
85 1295e769 Scott Ullrich
function parse_config($parse = false) {
86 7c841634 Christian McDonald
	global $g, $config_parsed, $config_extra;
87 02e9880e Ermal
88 12df7edc Erik
	$lockkey = lock('config');
89 0af381c2 Scott Ullrich
	$config_parsed = false;
90 02e9880e Ermal
91 12df7edc Erik
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
92
		$last_backup = discover_last_backup();
93 1e0b1727 Phil Davis
		if ($last_backup) {
94 4e038d31 Carlos Eduardo Ramos
			log_error(gettext("No config.xml found, attempting last known config restore."));
95
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
96 12df7edc Erik
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
97
		} else {
98
			unlock($lockkey);
99 4e038d31 Carlos Eduardo Ramos
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
100 12df7edc Erik
		}
101
	}
102 02e9880e Ermal
103 086cf944 Phil Davis
	if (platform_booting(true)) {
104 02e9880e Ermal
		echo ".";
105 086cf944 Phil Davis
	}
106 02e9880e Ermal
107 12df7edc Erik
	// Check for encrypted config.xml
108
	encrypted_configxml();
109 02e9880e Ermal
110 1e0b1727 Phil Davis
	if (!$parse) {
111 2568e151 Christian McDonald
		if (file_exists(g_get('tmp_path') . '/config.cache')) {
112
			$config = unserialize(file_get_contents(g_get('tmp_path') . '/config.cache'));
113 adb6925e Chris Buechler
			if (!is_array($config)) {
114 02e9880e Ermal
				$parse = true;
115 1e0b1727 Phil Davis
			}
116
		} else {
117 02e9880e Ermal
			$parse = true;
118 1e0b1727 Phil Davis
		}
119 02e9880e Ermal
	}
120
	if ($parse == true) {
121 2568e151 Christian McDonald
		if (!file_exists(g_get('conf_path') . "/config.xml")) {
122 1e0b1727 Phil Davis
			if (platform_booting(true)) {
123 02e9880e Ermal
				echo ".";
124 1e0b1727 Phil Davis
			}
125 12df7edc Erik
			log_error("No config.xml found, attempting last known config restore.");
126
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
127
			$last_backup = discover_last_backup();
128 1e0b1727 Phil Davis
			if ($last_backup) {
129 12df7edc Erik
				restore_backup("/cf/conf/backup/{$last_backup}");
130 1e0b1727 Phil Davis
			} else {
131 4e038d31 Carlos Eduardo Ramos
				log_error(gettext("Could not restore config.xml."));
132 50cafcf3 Ermal
				unlock($lockkey);
133 4816e5ca Renato Botelho
				die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
134 50cafcf3 Ermal
			}
135 12df7edc Erik
		}
136 2568e151 Christian McDonald
		$config = parse_xml_config(g_get('conf_path') . '/config.xml', array(g_get('xml_rootobj'), 'pfsense'));
137 1e0b1727 Phil Davis
		if ($config == -1) {
138 12df7edc Erik
			$last_backup = discover_last_backup();
139 1e0b1727 Phil Davis
			if ($last_backup) {
140 12df7edc Erik
				restore_backup("/cf/conf/backup/{$last_backup}");
141 1e0b1727 Phil Davis
			} else {
142 12df7edc Erik
				log_error(gettext("Could not restore config.xml."));
143 50cafcf3 Ermal
				unlock($lockkey);
144
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
145
			}
146 12df7edc Erik
		}
147
		generate_config_cache($config);
148
	}
149 02e9880e Ermal
150 1e0b1727 Phil Davis
	if (platform_booting(true)) {
151 02e9880e Ermal
		echo ".";
152 1e0b1727 Phil Davis
	}
153 02e9880e Ermal
154 12df7edc Erik
	$config_parsed = true;
155
	unlock($lockkey);
156
157
	return $config;
158
}
159
160
/****f* config/generate_config_cache
161
 * NAME
162
 *   generate_config_cache - Write serialized configuration to cache.
163
 * INPUTS
164
 *   $config	- array containing current firewall configuration
165
 * RESULT
166
 *   boolean	- true on completion
167
 ******/
168
function generate_config_cache($config) {
169 7c841634 Christian McDonald
	global $g, $config_extra;
170 12df7edc Erik
171 2568e151 Christian McDonald
	$configcache = fopen(g_get('tmp_path') . '/config.cache', "w");
172 12df7edc Erik
	fwrite($configcache, serialize($config));
173
	fclose($configcache);
174 7c841634 Christian McDonald
	//pfSense_fsync("{$g['tmp_path']}/config.cache");
175
176
	unset($configcache);
177
	/* Used for config.extra.xml */
178 2568e151 Christian McDonald
	if (file_exists(g_get('tmp_path') . '/config.extra.cache') && $config_extra) {
179
		$configcacheextra = fopen(g_get('tmp_path') . '/config.extra.cache', "w");
180 7c841634 Christian McDonald
		fwrite($configcacheextra, serialize($config_extra));
181
		fclose($configcacheextra);
182
		//pfSense_fsync("{$g['tmp_path']}/config.extra.cache");
183
		unset($configcacheextra);
184
	}
185 12df7edc Erik
}
186
187
function discover_last_backup() {
188 40159e4f Viktor G
	global $g;
189
190 692c21fd Renato Botelho
	$backups = glob('/cf/conf/backup/*.xml');
191 40159e4f Viktor G
	foreach (array_reverse($backups) as $backup) {
192
		/* checking multiple backups when detecting invalid configuration
193
		 * https://redmine.pfsense.org/issues/11748 */
194
		if (filesize($backup) != 0) {
195 2568e151 Christian McDonald
			$testconfig = parse_xml_config($backup, g_get('xml_rootobj'));
196 40159e4f Viktor G
			if ($testconfig != -1) {
197
				return basename($backup);
198
			}
199
		} 
200 692c21fd Renato Botelho
	}
201 12df7edc Erik
202 40159e4f Viktor G
	return false;
203 12df7edc Erik
}
204
205
function restore_backup($file) {
206
	global $g;
207
208
	if (file_exists($file)) {
209 b3cc5117 Viktor G
		/* restore rrddata/xmldata and clear appropriate data,
210
		 * see https://redmine.pfsense.org/issues/11050 */
211
		$data = file_get_contents("$file");
212 2568e151 Christian McDonald
		$conf = parse_xml_config("$file", g_get('xml_rootobj'));
213 b3cc5117 Viktor G
		if ($conf['rrddata']) {
214
			restore_rrddata($conf);
215
			$data = clear_tagdata("rrd", $data);
216
		}
217 dc22e511 Viktor G
		if ($conf['sshdata']) {
218
			restore_sshdata($conf);
219
			$data = clear_tagdata("ssh", $data);
220
		}
221 2568e151 Christian McDonald
		foreach (g_get('backuppath') as $bk => $path) {
222 b3cc5117 Viktor G
			if (!empty($conf[$bk][$bk.'data'])) {
223
				restore_xmldatafile($bk, $conf);
224
				$data = clear_tagdata($bk, $data);
225
			}
226
		}
227
		file_put_contents($file, $data);
228 12df7edc Erik
		unlink_if_exists("{$g['tmp_path']}/config.cache");
229 086cf944 Phil Davis
		copy("$file", "/cf/conf/config.xml");
230 c5663bf5 Renato Botelho
		//pfSense_fsync("/cf/conf/config.xml");
231
		//pfSense_fsync($g['conf_path']);
232 0f806eca Erik Fonnesbeck
		disable_security_checks();
233 2568e151 Christian McDonald
		log_error(sprintf(gettext('%1$s is restoring the configuration %2$s'), g_get('product_label'), $file));
234
		file_notice("config.xml", sprintf(gettext('%1$s is restoring the configuration %2$s'), g_get('product_label'), $file), "pfSenseConfigurator", "");
235 12df7edc Erik
	}
236
}
237
238 b3cc5117 Viktor G
/*
239
 *	Backup RRD/XML Data
240
 */
241
242
/* If the config on disk had rrddata/xmldata tags already, remove that section first.
243
 * See https://redmine.pfsense.org/issues/8994,
244
 *     https://redmine.pfsense.org/issues/10508, 
245
 *     https://redmine.pfsense.org/issues/11050 */
246 de3f6463 Reid Linnemann
function clear_tagdata($tag, $data) {
247 b3cc5117 Viktor G
	$data = preg_replace("/[[:blank:]]*<{$tag}data>.*<\\/{$tag}data>[[:blank:]]*\n*/s", "", $data);
248
	$data = preg_replace("/[[:blank:]]*<{$tag}data\\/>[[:blank:]]*\n*/", "", $data);
249
250
	return $data;
251
}
252
253
function restore_xmldatafile($type='voucher', $conf = false) {
254
	global $config, $g;
255
256
	if (!$conf) {
257
		$conf = & $config;
258
	}
259
260
	foreach ($conf[$type]["{$type}data"]["xmldatafile"] as $file) {
261
		$basename = basename($file['filename']);
262
		$dirname = dirname($g['backuppath'][$type]);
263
		$xmldata_file = "{$dirname}/{$basename}";
264 eca0a3ac Viktor G
		if (!is_dir($dirname)) {
265
			safe_mkdir($dirname);
266
		}
267 b3cc5117 Viktor G
		if (file_put_contents($xmldata_file, gzinflate(base64_decode($file['data']))) === false) {
268
			log_error(sprintf(gettext("Cannot write %s"), $xmldata_file));
269
			continue;
270
		}
271
	}
272
}
273
274
function restore_rrddata($conf = false) {
275
	global $config, $g, $rrdtool, $input_errors;
276
277
	if (!$conf) {
278
		$conf = & $config;
279
	}
280
281
	foreach ($conf['rrddata']['rrddatafile'] as $rrd) {
282
		if ($rrd['xmldata']) {
283 ca80d184 jim-p
			$rrd_file = "{$g['vardb_path']}/rrd/" . basename($rrd['filename']);
284 b3cc5117 Viktor G
			$xml_file = preg_replace('/\.rrd$/', ".xml", $rrd_file);
285
			if (file_put_contents($xml_file, gzinflate(base64_decode($rrd['xmldata']))) === false) {
286
				log_error(sprintf(gettext("Cannot write %s"), $xml_file));
287
				continue;
288
			}
289
			$output = array();
290
			$status = null;
291 ca80d184 jim-p
			exec("{$rrdtool} restore -f " . escapeshellarg($xml_file) . ' ' . escapeshellarg($rrd_file), $output, $status);
292 b3cc5117 Viktor G
			if ($status) {
293
				log_error("rrdtool restore -f '{$xml_file}' '{$rrd_file}' failed returning {$status}.");
294
				continue;
295
			}
296
			unlink($xml_file);
297
		} else if ($rrd['data']) {
298 ca80d184 jim-p
			$rrd_file = "{$g['vardb_path']}/rrd/" . basename($rrd['filename']);
299 b3cc5117 Viktor G
			$rrd_fd = fopen($rrd_file, "w");
300
			if (!$rrd_fd) {
301
				log_error(sprintf(gettext("Cannot write %s"), $rrd_file));
302
				continue;
303
			}
304
			$data = base64_decode($rrd['data']);
305
			/* Try to decompress the data. */
306
			$dcomp = @gzinflate($data);
307
			if ($dcomp) {
308
				/* If the decompression worked, write the decompressed data */
309
				if (fwrite($rrd_fd, $dcomp) === false) {
310
					log_error(sprintf(gettext("fwrite %s failed"), $rrd_file));
311
					continue;
312
				}
313
			} else {
314
				/* If the decompression failed, it wasn't compressed, so write raw data */
315
				if (fwrite($rrd_fd, $data) === false) {
316
					log_error(sprintf(gettext("fwrite %s failed"), $rrd_file));
317
					continue;
318
				}
319
			}
320
			if (fclose($rrd_fd) === false) {
321
				log_error(sprintf(gettext("fclose %s failed"), $rrd_file));
322
				continue;
323
			}
324
		}
325
	}
326
}
327
328 dc22e511 Viktor G
function restore_sshdata($conf = false) {
329
	global $config, $sshConfigDir;
330
331
	if (!$conf) {
332
		$conf = & $config;
333
	}
334
335 49eba660 Viktor G
	$oldmask = umask();
336 dc22e511 Viktor G
	foreach ($conf["sshdata"]["sshkeyfile"] as $sshkey) {
337
		$keypath = "{$sshConfigDir}/{$sshkey['filename']}";
338 49eba660 Viktor G
		if (strstr($sshkey['filename'], 'pub')) {
339
			umask(0133);
340
		} else {
341
			umask(0177);
342
		}
343 dc22e511 Viktor G
		if (file_put_contents($keypath, gzinflate(base64_decode($sshkey['xmldata']))) === false) {
344
			log_error(sprintf(gettext("Cannot write %s"), $sshkey['filename']));
345
			continue;
346
		}
347
	}
348 49eba660 Viktor G
	umask($oldmask);
349 dc22e511 Viktor G
}
350
351 12df7edc Erik
/****f* config/parse_config_bootup
352
 * NAME
353
 *   parse_config_bootup - Bootup-specific configuration checks.
354
 * RESULT
355
 *   null
356
 ******/
357
function parse_config_bootup() {
358 50cafcf3 Ermal
	global $config, $g;
359 12df7edc Erik
360 1e0b1727 Phil Davis
	if (platform_booting()) {
361 02e9880e Ermal
		echo ".";
362 1e0b1727 Phil Davis
	}
363 12df7edc Erik
364
	$lockkey = lock('config');
365 50cafcf3 Ermal
	if (!file_exists("{$g['conf_path']}/config.xml")) {
366 285ef132 Ermal LUÇI
		if (platform_booting()) {
367 60f164f3 Renato Botelho
			$last_backup = discover_last_backup();
368
			if ($last_backup) {
369
				log_error("No config.xml found, attempting last known config restore.");
370
				file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
371
				restore_backup("/cf/conf/backup/{$last_backup}");
372
			}
373
			if (!file_exists("{$g['conf_path']}/config.xml")) {
374 2568e151 Christian McDonald
				echo sprintf(gettext("XML configuration file not found.  %s cannot continue booting."), g_get('product_label')) . "\n";
375 60f164f3 Renato Botelho
				unlock($lockkey);
376 5fff62d9 Viktor G
				die(gettext("Could not find a usable configuration file or it's backup! Exiting...."));
377 658b4b7f Viktor G
			} else {
378
				log_error("Last known config found and restored.  Please double check the configuration file for accuracy.");
379
				file_notice("config.xml", gettext("Last known config found and restored.  Please double check the configuration file for accuracy."), "pfSenseConfigurator", "");
380 12df7edc Erik
			}
381 50cafcf3 Ermal
		} else {
382
			unlock($lockkey);
383 b5e8282d Ermal
			log_error(gettext("Could not find a usable configuration file! Exiting...."));
384 50cafcf3 Ermal
			exit(0);
385 12df7edc Erik
		}
386
	}
387 50cafcf3 Ermal
388 12df7edc Erik
	if (filesize("{$g['conf_path']}/config.xml") == 0) {
389
		$last_backup = discover_last_backup();
390 1e0b1727 Phil Davis
		if ($last_backup) {
391 4e038d31 Carlos Eduardo Ramos
			log_error(gettext("No config.xml found, attempting last known config restore."));
392
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
393 12df7edc Erik
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
394
		} else {
395
			unlock($lockkey);
396 4e038d31 Carlos Eduardo Ramos
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
397 12df7edc Erik
		}
398
	}
399
	unlock($lockkey);
400
401 89adb2f3 Ermal
	$config = parse_config(true);
402
403 2568e151 Christian McDonald
	if ((float)$config['version'] > (float)g_get('latest_config')) {
404 12df7edc Erik
		echo <<<EOD
405
406
407
*******************************************************************************
408
* WARNING!                                                                    *
409 573ec19d Renato Botelho do Couto
* The current configuration has been created with a newer version of {$g['product_label']}  *
410 12df7edc Erik
* than this one! This can lead to serious misbehavior and even security       *
411 573ec19d Renato Botelho do Couto
* holes! You are urged to either upgrade to a newer version of {$g['product_label']} or     *
412 12df7edc Erik
* revert to the default configuration immediately!                            *
413
*******************************************************************************
414
415
416
EOD;
417
		}
418
419
	/* make alias table (for faster lookups) */
420 dbc1b8ee jim-p
	alias_make_table();
421 12df7edc Erik
}
422
423 632f0dbf Renato Botelho
/****f* config/conf_mount_rw
424
 * NAME
425
 *   conf_mount_rw - Mount filesystems read/write.
426
 * RESULT
427
 *   null
428
 ******/
429
/* mount flash card read/write */
430
function conf_mount_rw() {
431 f3f98e97 Phil Davis
	/* Obsoleted. Keep it here until all calls are removed */
432 632f0dbf Renato Botelho
	return;
433
}
434
435
/****f* config/conf_mount_ro
436
 * NAME
437
 *   conf_mount_ro - Mount filesystems readonly.
438
 * RESULT
439
 *   null
440
 ******/
441
function conf_mount_ro() {
442 f3f98e97 Phil Davis
	/* Obsoleted. Keep it here until all calls are removed */
443 632f0dbf Renato Botelho
	return;
444
}
445
446 12df7edc Erik
/****f* config/convert_config
447
 * NAME
448
 *   convert_config - Attempt to update config.xml.
449
 * DESCRIPTION
450
 *   convert_config() reads the current global configuration
451
 *   and attempts to convert it to conform to the latest
452
 *   config.xml version. This allows major formatting changes
453
 *   to be made with a minimum of breakage.
454
 * RESULT
455
 *   null
456
 ******/
457
/* convert configuration, if necessary */
458
function convert_config() {
459
	global $config, $g;
460
	$now = date("H:i:s");
461 4e038d31 Carlos Eduardo Ramos
	log_error(sprintf(gettext("Start Configuration upgrade at %s, set execution timeout to 15 minutes"), $now));
462 59cfe65d Ermal
	//ini_set("max_execution_time", "900");
463 12df7edc Erik
464
	/* special case upgrades */
465
	/* fix every minute crontab bogons entry */
466 32a9eb18 Ermal
	if (is_array($config['cron'])) {
467
		$cron_item_count = count($config['cron']['item']);
468 086cf944 Phil Davis
		for ($x = 0; $x < $cron_item_count; $x++) {
469 1e0b1727 Phil Davis
			if (stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
470 086cf944 Phil Davis
				if ($config['cron']['item'][$x]['hour'] == "*") {
471 1e0b1727 Phil Davis
					$config['cron']['item'][$x]['hour'] = "3";
472 32a9eb18 Ermal
					write_config(gettext("Updated bogon update frequency to 3am"));
473
					log_error(gettext("Updated bogon update frequency to 3am"));
474 1e0b1727 Phil Davis
				}
475 32a9eb18 Ermal
			}
476 12df7edc Erik
		}
477
	}
478
479
	// Save off config version
480 1e45d13f Christian McDonald
	$prev_version = config_get_path('version');
481 1e0b1727 Phil Davis
482 b96cad97 Seth Mos
	include_once('auth.inc');
483 12df7edc Erik
	include_once('upgrade_config.inc');
484 1e0b1727 Phil Davis
	if (file_exists("/etc/inc/upgrade_config_custom.inc")) {
485 e58da189 Ermal
		include_once("upgrade_config_custom.inc");
486 1e0b1727 Phil Davis
	}
487 acaafa7f Renato Botelho
488 2568e151 Christian McDonald
	if ($config['version'] == g_get('latest_config')) {
489 f6b65ad8 Renato Botelho
		additional_config_upgrade();
490
		return;		/* already at latest version */
491
	}
492
493 acaafa7f Renato Botelho
	if (!is_array($config['system']['already_run_config_upgrade'])) {
494
		$config['system']['already_run_config_upgrade'] = array();
495
	}
496 1e45d13f Christian McDonald
	$already_run = config_get_path('system/already_run_config_upgrade');
497 acaafa7f Renato Botelho
498 12df7edc Erik
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
499 2568e151 Christian McDonald
	while ($config['version'] < g_get('latest_config')) {
500 12df7edc Erik
		$cur = $config['version'] * 10;
501
		$next = $cur + 1;
502 acaafa7f Renato Botelho
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur,
503
		    $next);
504
505
		foreach (array("", "_custom") as $suffix) {
506
			$migration_function .= $suffix;
507
			if (!function_exists($migration_function)) {
508
				continue;
509
			}
510
			if (isset($already_run[$migration_function])) {
511 7e3ea4a8 Christian McDonald
				config_del_path("system/already_run_config_upgrade/{$migration_function}");
512 acaafa7f Renato Botelho
			} else {
513
				$migration_function();
514
			}
515 1e0b1727 Phil Davis
		}
516 12df7edc Erik
		$config['version'] = sprintf('%.1f', $next / 10);
517 1e0b1727 Phil Davis
		if (platform_booting()) {
518 92cf9fcd sullrich
			echo ".";
519 1e0b1727 Phil Davis
		}
520 12df7edc Erik
	}
521
522 1e0b1727 Phil Davis
	if ($prev_version != $config['version']) {
523 f6b65ad8 Renato Botelho
		$now = date("H:i:s");
524
		log_error(sprintf(gettext("Ended Configuration upgrade at %s"), $now));
525
526 addc0439 Renato Botelho
		write_config(sprintf(gettext('Upgraded config version level from %1$s to %2$s'), $prev_version, $config['version']));
527 1e0b1727 Phil Davis
	}
528 f6b65ad8 Renato Botelho
529
	additional_config_upgrade();
530 12df7edc Erik
}
531
532 ddd42db3 Ermal Lu?i
/****f* config/safe_write_file
533
 * NAME
534
 *   safe_write_file - Write a file out atomically
535
 * DESCRIPTION
536
 *   safe_write_file() Writes a file out atomically by first writing to a
537
 *   temporary file of the same name but ending with the pid of the current
538
 *   process, them renaming the temporary file over the original.
539
 * INPUTS
540
 *   $filename  - string containing the filename of the file to write
541 406ced77 Renato Botelho
 *   $content   - string or array containing the file content to write to file
542 ddd42db3 Ermal Lu?i
 *   $force_binary      - boolean denoting whether we should force binary
543
 *   mode writing.
544
 * RESULT
545
 *   boolean - true if successful, false if not
546
 ******/
547 e717f161 Renato Botelho
function safe_write_file($file, $content, $force_binary = false) {
548 628d1548 Ermal
	$tmp_file = $file . "." . getmypid();
549
	$write_mode = $force_binary ? "wb" : "w";
550 ddd42db3 Ermal Lu?i
551 628d1548 Ermal
	$fd = fopen($tmp_file, $write_mode);
552
	if (!$fd) {
553
		// Unable to open temporary file for writing
554
		return false;
555 1e0b1727 Phil Davis
	}
556 406ced77 Renato Botelho
	if (is_array($content)) {
557
		foreach ($content as $line) {
558
			if (!fwrite($fd, $line . "\n")) {
559
				// Unable to write to temporary file
560
				fclose($fd);
561
				return false;
562
			}
563
		}
564
	} elseif (!fwrite($fd, $content)) {
565 628d1548 Ermal
		// Unable to write to temporary file
566 00bc5bcc Scott Ullrich
		fclose($fd);
567 628d1548 Ermal
		return false;
568
	}
569
	fflush($fd);
570
	fclose($fd);
571 ddd42db3 Ermal Lu?i
572 c03dc57f Renato Botelho
	/* XXX Re-add pfSense_fsync() call here after it's fixed */
573
	// if (!pfSense_fsync($tmp_file) || !rename($tmp_file, $file)) {
574
	if (!rename($tmp_file, $file)) {
575 628d1548 Ermal
		// Unable to move temporary file to original
576
		@unlink($tmp_file);
577
		return false;
578
	}
579 00bc5bcc Scott Ullrich
580 628d1548 Ermal
	// Sync file before returning
581 c5663bf5 Renato Botelho
	//return pfSense_fsync($file);
582
	return true;
583 ddd42db3 Ermal Lu?i
}
584
585 12df7edc Erik
/****f* config/write_config
586
 * NAME
587
 *   write_config - Backup and write the firewall configuration.
588
 * DESCRIPTION
589
 *   write_config() handles backing up the current configuration,
590
 *   applying changes, and regenerating the configuration cache.
591
 * INPUTS
592
 *   $desc	- string containing the a description of configuration changes
593
 *   $backup	- boolean: do not back up current configuration if false.
594 f5315ac1 NOYB
 *   $write_config_only	- boolean: do not sync or reload anything; just save the configuration if true.
595 12df7edc Erik
 * RESULT
596
 *   null
597
 ******/
598
/* save the system configuration */
599 429e0911 NOYB
function write_config($desc="Unknown", $backup = true, $write_config_only = false) {
600 12df7edc Erik
	global $config, $g;
601
602 6f6299a3 Steve Beaver
	// Certain strings may be embedded in the $desc (reason) parameter to trigger certain behavior.
603 f3f98e97 Phil Davis
	// If detected, those strings are removed and a variable set.
604 6f6299a3 Steve Beaver
	$doacb = true;
605
	$manual_acb = false;
606
	$rcnt = 0;
607
608
	$desc = str_replace("-MaNuAlBaCkUp", "", $desc, $rcnt);
609
	if ($rcnt > 0) {
610
		$manual_acb = true; // Manual backups require special processing on the server
611
	}
612
613
	$rcnt = 0;
614
	$desc = str_replace("-NoReMoTeBaCkUp", "", $desc, $rcnt);
615
	if ($rcnt > 0) {
616
		$doacb = false; // No ACB will be performed if this string is detected
617
	}
618
619
	/*
620
	* Syncing vouchers happens every minute and sometimes multiple times. We don't
621
	* want to fill up our db with a lot of the same config so just ignore that case.
622
	*/
623
	if((strpos($desc, 'Syncing vouchers') !== false ||
624
		strpos($desc, 'Captive Portal Voucher database synchronized') !== false) ) {
625
		$doacb = false;
626
	}
627
628 a74260cb jim-p
	if (!empty($_SERVER['REMOTE_ADDR'])) {
629 82cd6022 PiBa-NL
		@phpsession_begin();
630 cf0dae69 Ermal
		if (!empty($_SESSION['Username']) && ($_SESSION['Username'] != "admin")) {
631
			$user = getUserEntry($_SESSION['Username']);
632
			if (is_array($user) && userHasPrivilege($user, "user-config-readonly")) {
633 d629601a jim-p
				syslog(LOG_AUTHPRIV, sprintf(gettext("Save config permission denied by the 'User - Config: Deny Config Write' permission for user '%s'."), get_config_user()));
634 82cd6022 PiBa-NL
				phpsession_end(true);
635 cf0dae69 Ermal
				return false;
636
			}
637 4111fcf5 Ermal
		}
638 82cd6022 PiBa-NL
		if (!isset($argc)) {
639
			phpsession_end(true);
640
		}
641 170cb2bc jim-p
	}
642 4111fcf5 Ermal
643 3dcaae88 Phil Davis
	if (isset($config['reset_factory_defaults'])) {
644
		/*
645
		   We have put a default config.xml on disk and are about to reboot
646
		   or reload it. Do not let any system or package code try to save
647
		   state to config because that would overwrite the default config
648
		   with the running config.
649
		*/
650
		return false;
651
	}
652 4111fcf5 Ermal
653 1e0b1727 Phil Davis
	if ($backup) {
654 12df7edc Erik
		backup_config();
655 1e0b1727 Phil Davis
	}
656 12df7edc Erik
657 b704b6ef Renato Botelho do Couto
	if ($desc == "Unknown") {
658
		file_notice("config.xml", gettext(
659
		    'WARNING: write_config() was called without description'));
660
	}
661 ba1d9714 jim-p
	$config['revision'] = make_config_revision_entry($desc);
662 12df7edc Erik
663 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
664 12df7edc Erik
665
	/* generate configuration XML */
666 2568e151 Christian McDonald
	$xmlconfig = dump_xml_config($config, g_get('xml_rootobj'));
667 12df7edc Erik
668 41bf8e8e Scott Ullrich
	/* write new configuration */
669 e717f161 Renato Botelho
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig)) {
670 89a8d28e Chris Buechler
		log_error(gettext("WARNING: Config contents could not be saved. Could not open file!"));
671 12df7edc Erik
		unlock($lockkey);
672 2568e151 Christian McDonald
		file_notice("config.xml", sprintf(gettext('Unable to open %1$s/config.xml for writing in write_config()%2$s'), g_get('cf_conf_path'), "\n"));
673 541989d5 Ermal
		return -1;
674 e5977136 Scott Ullrich
	}
675 1e0b1727 Phil Davis
676 fca0f301 jim-p
	if (config_get_path('syslog/logconfigchanges') != "disabled") {
677 8d51efb6 jim-p
		log_error(gettext("Configuration Change") . ": {$config['revision']['description']}");
678
	}
679
680 e1ebe9e2 jim-p
	cleanup_backupcache(true);
681 12df7edc Erik
682
	/* re-read configuration */
683 541989d5 Ermal
	/* NOTE: We assume that the file can be parsed since we wrote it. */
684 2568e151 Christian McDonald
	$config = parse_xml_config("{$g['conf_path']}/config.xml", g_get('xml_rootobj'));
685 e490f995 Ermal
	if ($config == -1) {
686 557300a7 jim-p
		copy("{$g['conf_path']}/config.xml", "{$g['conf_path']}/config.xml.bad");
687 e490f995 Ermal
		$last_backup = discover_last_backup();
688 557300a7 jim-p
		if ($last_backup) {
689 e490f995 Ermal
			restore_backup("/cf/conf/backup/{$last_backup}");
690 2568e151 Christian McDonald
			$config = parse_xml_config("{$g['conf_path']}/config.xml", g_get('xml_rootobj'));
691 285ef132 Ermal LUÇI
			if (platform_booting()) {
692 557300a7 jim-p
				echo "\n\n ************** WARNING **************";
693 6177fd92 jim-p
				echo "\n\n Configuration could not be validated. A previous configuration was restored. \n";
694 05d5503b Ermal
				echo "\n The failed configuration file has been saved as {$g['conf_path']}/config.xml.bad \n\n";
695 557300a7 jim-p
			}
696 1e0b1727 Phil Davis
		} else {
697 e490f995 Ermal
			log_error(gettext("Could not restore config.xml."));
698 1e0b1727 Phil Davis
		}
699
	} else {
700 e490f995 Ermal
		generate_config_cache($config);
701 1e0b1727 Phil Davis
	}
702 12df7edc Erik
703
	unlock($lockkey);
704
705 429e0911 NOYB
	if ($write_config_only) {
706
		return $config;
707
	}
708
709 12df7edc Erik
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
710 16b96ea6 Scott Ullrich
711 12df7edc Erik
	/* sync carp entries to other firewalls */
712 16b96ea6 Scott Ullrich
	carp_sync_client();
713 12df7edc Erik
714 1e0b1727 Phil Davis
	if (is_dir("/usr/local/pkg/write_config")) {
715 12df7edc Erik
		/* process packager manager custom rules */
716
		run_plugins("/usr/local/pkg/write_config/");
717
	}
718
719 587315d5 Steve Beaver
	// Try the core AutoConfigBackup system
720 a1aa91de Steve Beaver
	if (is_array($config['system']['acb']) && $config['system']['acb']['enable'] == "yes" &&
721
	    (!isset($config['system']['acb']['frequency']) || $config['system']['acb']['frequency'] == "every") || file_exists("/tmp/forceacb")) {
722 6f6299a3 Steve Beaver
	    if ($doacb) {
723
			require_once("acb.inc");
724
			upload_config($manual_acb);
725
		}
726
727 a1aa91de Steve Beaver
		if (file_exists("/tmp/forceacb")) {
728
			unlink("/tmp/forceacb");
729
		}
730 587315d5 Steve Beaver
	}
731
732 12df7edc Erik
	return $config;
733
}
734
735
/****f* config/reset_factory_defaults
736
 * NAME
737
 *   reset_factory_defaults - Reset the system to its default configuration.
738
 * RESULT
739
 *   integer	- indicates completion
740
 ******/
741 7d7da5e5 Phil Davis
function reset_factory_defaults($lock = false, $reboot_required = true) {
742 3dcaae88 Phil Davis
	global $config, $g;
743 12df7edc Erik
744 961884ae Renato Botelho
	/* Remove all additional packages */
745 5e8c3fa0 Renato Botelho
	mwexec("/bin/sh /usr/local/sbin/{$g['product_name']}-upgrade " .
746 1220cb90 Renato Botelho
	    "-r ALL_PACKAGES -f");
747 7222324e Renato Botelho
748 1e0b1727 Phil Davis
	if (!$lock) {
749 b6c34bfc Ermal
		$lockkey = lock('config', LOCK_EX);
750 1e0b1727 Phil Davis
	}
751 12df7edc Erik
752
	/* create conf directory, if necessary */
753 2568e151 Christian McDonald
	safe_mkdir(g_get('cf_conf_path'));
754 12df7edc Erik
755
	/* clear out /conf */
756 2568e151 Christian McDonald
	$dh = opendir(g_get('conf_path'));
757 12df7edc Erik
	while ($filename = readdir($dh)) {
758 5e8c3fa0 Renato Botelho
		if (($filename != ".") && ($filename != "..") &&
759 2568e151 Christian McDonald
		    (!is_dir(g_get('conf_path') . "/" . $filename))) {
760 8e2de557 Luiz Otavio O Souza
			if ($filename == "enableserial_force")
761
				continue;
762 2568e151 Christian McDonald
			unlink_if_exists(g_get('conf_path') . "/" . $filename);
763 12df7edc Erik
		}
764
	}
765
	closedir($dh);
766 2568e151 Christian McDonald
	unlink_if_exists(g_get('tmp_path') . "/config.cache");
767 12df7edc Erik
768
	/* copy default configuration */
769 5e8c3fa0 Renato Botelho
	copy("{$g['conf_default_path']}/config.xml",
770
	    "{$g['cf_conf_path']}/config.xml");
771 12df7edc Erik
772 0f806eca Erik Fonnesbeck
	disable_security_checks();
773
774 3dcaae88 Phil Davis
	/*
775
	   Let write_config know that we are awaiting reload of the current config
776
	   to factory defaults. Either the system is about to reboot, throwing away
777
	   the current in-memory config as it shuts down, or the in-memory config
778
	   is about to be reloaded on-the-fly by parse_config.
779
780
	   In both cases, we want to ensure that write_config does not flush the
781
	   in-memory config back to disk.
782
	*/
783
	$config['reset_factory_defaults'] = true;
784
785 12df7edc Erik
	/* call the wizard */
786 7d7da5e5 Phil Davis
	if ($reboot_required) {
787
		// If we need a reboot first then touch a different trigger file.
788
		touch("/conf/trigger_initial_wizard_after_reboot");
789
	} else {
790
		touch("/conf/trigger_initial_wizard");
791
	}
792 1e0b1727 Phil Davis
	if (!$lock) {
793 12df7edc Erik
		unlock($lockkey);
794 1e0b1727 Phil Davis
	}
795 749dfdb7 Luiz Souza
	console_configure();
796 12df7edc Erik
	return 0;
797
}
798
799
function config_restore($conffile) {
800
	global $config, $g;
801
802 1e0b1727 Phil Davis
	if (!file_exists($conffile)) {
803 12df7edc Erik
		return 1;
804 1e0b1727 Phil Davis
	}
805 12df7edc Erik
806
	backup_config();
807
808 1e0b1727 Phil Davis
809 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
810 12df7edc Erik
811
	unlink_if_exists("{$g['tmp_path']}/config.cache");
812 e490f995 Ermal
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
813 12df7edc Erik
814 0f806eca Erik Fonnesbeck
	disable_security_checks();
815
816 12df7edc Erik
	unlock($lockkey);
817
818
	$config = parse_config(true);
819
820
821 d18f3f6e Phil Davis
	write_config(sprintf(gettext("Reverted to %s."), array_pop(explode("/", $conffile))), false);
822 e296b183 Ermal Lu?i
823 12df7edc Erik
	return 0;
824
}
825
826
function config_install($conffile) {
827
	global $config, $g;
828
829 1e0b1727 Phil Davis
	if (!file_exists($conffile)) {
830 12df7edc Erik
		return 1;
831 1e0b1727 Phil Davis
	}
832 12df7edc Erik
833 1e0b1727 Phil Davis
	if (!config_validate("{$conffile}")) {
834 12df7edc Erik
		return 1;
835 1e0b1727 Phil Davis
	}
836 12df7edc Erik
837 1e0b1727 Phil Davis
	if (platform_booting()) {
838 4e038d31 Carlos Eduardo Ramos
		echo gettext("Installing configuration...") . "\n";
839 1e0b1727 Phil Davis
	} else {
840 4e038d31 Carlos Eduardo Ramos
		log_error(gettext("Installing configuration ...."));
841 1e0b1727 Phil Davis
	}
842 12df7edc Erik
843 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
844 12df7edc Erik
845
	copy($conffile, "{$g['conf_path']}/config.xml");
846
847 0f806eca Erik Fonnesbeck
	disable_security_checks();
848
849 12df7edc Erik
	/* unlink cache file if it exists */
850 1e0b1727 Phil Davis
	if (file_exists("{$g['tmp_path']}/config.cache")) {
851 12df7edc Erik
		unlink("{$g['tmp_path']}/config.cache");
852 1e0b1727 Phil Davis
	}
853 12df7edc Erik
854
	unlock($lockkey);
855
856 1e0b1727 Phil Davis
	return 0;
857 12df7edc Erik
}
858
859 0f806eca Erik Fonnesbeck
/*
860
 * Disable security checks for DNS rebind and HTTP referrer until next time
861
 * they pass (or reboot), to aid in preventing accidental lockout when
862
 * restoring settings like hostname, domain, IP addresses, and settings
863
 * related to the DNS rebind and HTTP referrer checks.
864
 * Intended for use when restoring a configuration or directly
865
 * modifying config.xml without an unconditional reboot.
866
 */
867
function disable_security_checks() {
868
	global $g;
869
	touch("{$g['tmp_path']}/disable_security_checks");
870
}
871
872
/* Restores security checks.  Should be called after all succeed. */
873
function restore_security_checks() {
874
	global $g;
875
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
876
}
877
878
/* Returns status of security check temporary disable. */
879
function security_checks_disabled() {
880
	global $g;
881
	return file_exists("{$g['tmp_path']}/disable_security_checks");
882
}
883
884 12df7edc Erik
function config_validate($conffile) {
885
886
	global $g, $xmlerr;
887
888
	$xml_parser = xml_parser_create();
889
890
	if (!($fp = fopen($conffile, "r"))) {
891 4e038d31 Carlos Eduardo Ramos
		$xmlerr = gettext("XML error: unable to open file");
892 12df7edc Erik
		return false;
893
	}
894
895
	while ($data = fread($fp, 4096)) {
896
		if (!xml_parse($xml_parser, $data, feof($fp))) {
897 addc0439 Renato Botelho
			$xmlerr = sprintf(gettext('%1$s at line %2$d'),
898 12df7edc Erik
						xml_error_string(xml_get_error_code($xml_parser)),
899
						xml_get_current_line_number($xml_parser));
900
			return false;
901
		}
902
	}
903
	xml_parser_free($xml_parser);
904
905
	fclose($fp);
906
907
	return true;
908
}
909
910 e1ebe9e2 jim-p
function cleanup_backupcache($lock = false) {
911 caec0e97 jim-p
	global $config, $g;
912 12df7edc Erik
	$i = false;
913 e1ebe9e2 jim-p
914 2568e151 Christian McDonald
	$revisions = intval(is_numericint($config['system']['backupcount']) ? $config['system']['backupcount'] : g_get('default_config_backup_count'));
915 e1ebe9e2 jim-p
916 1e0b1727 Phil Davis
	if (!$lock) {
917 12df7edc Erik
		$lockkey = lock('config');
918 1e0b1727 Phil Davis
	}
919 cd25a2b2 jim-p
920
921
	$backups = get_backups();
922
	if ($backups) {
923 12df7edc Erik
		$baktimes = $backups['versions'];
924
		unset($backups['versions']);
925 cd25a2b2 jim-p
	} else {
926
		$backups = array();
927
		$baktimes = array();
928
	}
929
	$newbaks = array();
930 2568e151 Christian McDonald
	$bakfiles = glob(g_get('cf_conf_path') . "/backup/config-*");
931 cd25a2b2 jim-p
	$tocache = array();
932 12df7edc Erik
933 1e0b1727 Phil Davis
	foreach ($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
934 bfe615ee jim-p
		$backupsize = filesize($backup);
935 1e0b1727 Phil Davis
		if ($backupsize == 0) {
936 cd25a2b2 jim-p
			unlink($backup);
937
			continue;
938
		}
939 b3bbed58 Ermal LUÇI
		$backupexp = explode('-', $backup);
940
		$backupexp = explode('.', array_pop($backupexp));
941
		$tocheck = array_shift($backupexp);
942
		unset($backupexp);
943 1e0b1727 Phil Davis
		if (!in_array($tocheck, $baktimes)) {
944 cd25a2b2 jim-p
			$i = true;
945 1e0b1727 Phil Davis
			if (platform_booting()) {
946 cd25a2b2 jim-p
				echo ".";
947 1e0b1727 Phil Davis
			}
948 6153d668 PiBa-NL
			try {
949 2568e151 Christian McDonald
				$newxml = parse_xml_config($backup, array(g_get('xml_rootobj'), 'pfsense'));
950 6153d668 PiBa-NL
			} catch (Exception $exc) {
951
				log_error(sprintf(gettext("The backup cache file %s is corrupted. Parser error message: %s"), $backup, $exc->getMessage()));
952
				$newxml = "-1";
953
			}
954
955 1e0b1727 Phil Davis
			if ($newxml == "-1") {
956 4e038d31 Carlos Eduardo Ramos
				log_error(sprintf(gettext("The backup cache file %s is corrupted.  Unlinking."), $backup));
957 cd25a2b2 jim-p
				unlink($backup);
958
				continue;
959 12df7edc Erik
			}
960 1e0b1727 Phil Davis
			if ($newxml['revision']['description'] == "") {
961 cd25a2b2 jim-p
				$newxml['revision']['description'] = "Unknown";
962 1e0b1727 Phil Davis
			}
963
			if ($newxml['version'] == "") {
964 92420c0a jim-p
				$newxml['version'] = "?";
965 1e0b1727 Phil Davis
			}
966 bfe615ee jim-p
			$tocache[$tocheck] = array('description' => $newxml['revision']['description'], 'version' => $newxml['version'], 'filesize' => $backupsize);
967 12df7edc Erik
		}
968 cd25a2b2 jim-p
	}
969 1e0b1727 Phil Davis
	foreach ($backups as $checkbak) {
970
		if (count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
971 cd25a2b2 jim-p
			$newbaks[] = $checkbak;
972
		} else {
973
			$i = true;
974 285ef132 Ermal LUÇI
			if (platform_booting()) print " " . $tocheck . "r";
975 cd25a2b2 jim-p
		}
976
	}
977 1e0b1727 Phil Davis
	foreach ($newbaks as $todo) {
978
		$tocache[$todo['time']] = array('description' => $todo['description'], 'version' => $todo['version'], 'filesize' => $todo['filesize']);
979
	}
980
	if (is_int($revisions) and (count($tocache) > $revisions)) {
981 cd25a2b2 jim-p
		$toslice = array_slice(array_keys($tocache), 0, $revisions);
982 3057a2ba jim-p
		$newcache = array();
983 1e0b1727 Phil Davis
		foreach ($toslice as $sliced) {
984 cd25a2b2 jim-p
			$newcache[$sliced] = $tocache[$sliced];
985 1e0b1727 Phil Davis
		}
986
		foreach ($tocache as $version => $versioninfo) {
987
			if (!in_array($version, array_keys($newcache))) {
988 2568e151 Christian McDonald
				unlink_if_exists(g_get('conf_path') . '/backup/config-' . $version . '.xml');
989 12df7edc Erik
			}
990
		}
991 cd25a2b2 jim-p
		$tocache = $newcache;
992 12df7edc Erik
	}
993 2568e151 Christian McDonald
	$bakout = fopen(g_get('cf_conf_path') . '/backup/backup.cache', "w");
994 cd25a2b2 jim-p
	fwrite($bakout, serialize($tocache));
995
	fclose($bakout);
996 c5663bf5 Renato Botelho
	//pfSense_fsync("{$g['cf_conf_path']}/backup/backup.cache");
997 cd25a2b2 jim-p
998 1e0b1727 Phil Davis
	if (!$lock) {
999 12df7edc Erik
		unlock($lockkey);
1000 1e0b1727 Phil Davis
	}
1001 12df7edc Erik
}
1002
1003
function get_backups() {
1004
	global $g;
1005 1e0b1727 Phil Davis
	if (file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
1006 12df7edc Erik
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
1007
		$bakvers = array_keys($confvers);
1008
		$toreturn = array();
1009
		sort($bakvers);
1010
		// 	$bakvers = array_reverse($bakvers);
1011 1e0b1727 Phil Davis
		foreach (array_reverse($bakvers) as $bakver) {
1012 bfe615ee jim-p
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description'], 'version' => $confvers[$bakver]['version'], 'filesize' => $confvers[$bakver]['filesize']);
1013 1e0b1727 Phil Davis
		}
1014 12df7edc Erik
	} else {
1015
		return false;
1016
	}
1017
	$toreturn['versions'] = $bakvers;
1018
	return $toreturn;
1019
}
1020
1021
function backup_config() {
1022
	global $config, $g;
1023
1024
1025
	/* Create backup directory if needed */
1026
	safe_mkdir("{$g['cf_conf_path']}/backup");
1027 1e0b1727 Phil Davis
	if ($config['revision']['time'] == "") {
1028
		$baktime = 0;
1029
	} else {
1030 1e45d13f Christian McDonald
		$baktime = config_get_path('revision/time');
1031 1e0b1727 Phil Davis
	}
1032 8a811010 Chris Buechler
1033 1e0b1727 Phil Davis
	if ($config['revision']['description'] == "") {
1034
		$bakdesc = "Unknown";
1035
	} else {
1036 1e45d13f Christian McDonald
		$bakdesc = config_get_path('revision/description');
1037 1e0b1727 Phil Davis
	}
1038 8059f9cb jim-p
1039
	$bakver = ($config['version'] == "") ? "?" : $config['version'];
1040 2568e151 Christian McDonald
	$bakfilename = g_get('cf_conf_path') . '/backup/config-' . $baktime . '.xml';
1041
	copy(g_get('cf_conf_path') . '/config.xml', $bakfilename);
1042 8a811010 Chris Buechler
1043 2568e151 Christian McDonald
	if (file_exists(g_get('cf_conf_path') . '/backup/backup.cache')) {
1044
		$backupcache = unserialize(file_get_contents(g_get('cf_conf_path') . '/backup/backup.cache'));
1045 1e0b1727 Phil Davis
	} else {
1046
		$backupcache = array();
1047
	}
1048 bfe615ee jim-p
	$backupcache[$baktime] = array('description' => $bakdesc, 'version' => $bakver, 'filesize' => filesize($bakfilename));
1049 2568e151 Christian McDonald
	$bakout = fopen(g_get('cf_conf_path') . '/backup/backup.cache', "w");
1050 1e0b1727 Phil Davis
	fwrite($bakout, serialize($backupcache));
1051
	fclose($bakout);
1052 c5663bf5 Renato Botelho
	//pfSense_fsync("{$g['cf_conf_path']}/backup/backup.cache");
1053 12df7edc Erik
1054
1055
	return true;
1056
}
1057
1058 db95baf1 Viktor G
function backup_info($backup_info, $number) {
1059
	if ($backup_info['time'] != 0) {
1060
		$date = date(gettext("n/j/y H:i:s"), $backup_info['time']);
1061
	} else {
1062
		$date = gettext("Unknown");
1063
	}
1064
1065
	list($page, $reason) = explode(": ", $backup_info['description'], 2);
1066
	if (empty($reason)) {
1067
		$reason = $page;
1068
		$page = gettext("Unknown Page");
1069
	}
1070
1071
	$backup_info = sprintf("%02d", $number) . ". {$date}\tv{$backup_info['version']}\t{$page}\n";
1072
	if ($reason) {
1073
		$backup_info .= "    {$reason}\n";
1074
	}
1075
	return $backup_info;
1076
}
1077
1078 12df7edc Erik
function set_device_perms() {
1079
	$devices = array(
1080 6c07db48 Phil Davis
		'pf' => array(
1081
			'user' => 'root',
1082
			'group' => 'proxy',
1083
			'mode' => 0660),
1084 12df7edc Erik
		);
1085
1086
	foreach ($devices as $name => $attr) {
1087
		$path = "/dev/$name";
1088
		if (file_exists($path)) {
1089
			chown($path, $attr['user']);
1090
			chgrp($path, $attr['group']);
1091
			chmod($path, $attr['mode']);
1092
		}
1093
	}
1094
}
1095
1096 ba1d9714 jim-p
function get_config_user() {
1097
	if (empty($_SESSION["Username"])) {
1098 362ec35d Ermal
		$username = getenv("USER");
1099 1e0b1727 Phil Davis
		if (empty($conuser) || $conuser == "root") {
1100 ba1d9714 jim-p
			$username = "(system)";
1101 1e0b1727 Phil Davis
		}
1102
	} else {
1103 ba1d9714 jim-p
		$username = $_SESSION["Username"];
1104 1e0b1727 Phil Davis
	}
1105 ba1d9714 jim-p
1106 1e0b1727 Phil Davis
	if (!empty($_SERVER['REMOTE_ADDR'])) {
1107 d629601a jim-p
		$username .= '@' . get_user_remote_address() . get_user_remote_authsource();
1108 1e0b1727 Phil Davis
	}
1109 ba1d9714 jim-p
1110
	return $username;
1111
}
1112
1113
function make_config_revision_entry($desc = null, $override_user = null) {
1114 1e0b1727 Phil Davis
	if (empty($override_user)) {
1115 ba1d9714 jim-p
		$username = get_config_user();
1116 1e0b1727 Phil Davis
	} else {
1117 ba1d9714 jim-p
		$username = $override_user;
1118 1e0b1727 Phil Davis
	}
1119 ba1d9714 jim-p
1120
	$revision = array();
1121
1122 1e0b1727 Phil Davis
	if (time() > mktime(0, 0, 0, 9, 1, 2004)) {     /* make sure the clock settings are plausible */
1123 ba1d9714 jim-p
		$revision['time'] = time();
1124 1e0b1727 Phil Davis
	}
1125 ba1d9714 jim-p
1126
	/* Log the running script so it's not entirely unlogged what changed */
1127 1e0b1727 Phil Davis
	if ($desc == "Unknown") {
1128 ba1d9714 jim-p
		$desc = sprintf(gettext("%s made unknown change"), $_SERVER['SCRIPT_NAME']);
1129 1e0b1727 Phil Davis
	}
1130
	if (!empty($desc)) {
1131 ba1d9714 jim-p
		$revision['description'] = "{$username}: " . $desc;
1132 1e0b1727 Phil Davis
	}
1133 ba1d9714 jim-p
	$revision['username'] = $username;
1134
	return $revision;
1135
}
1136
1137 00e55088 Ermal
function pfSense_clear_globals() {
1138 100b5040 BBcan177
	global $config, $g, $FilterIfList, $GatewaysList, $filterdns, $aliases, $aliastable;
1139 00e55088 Ermal
1140 be2d7eb7 Chris Buechler
	$error = error_get_last();
1141 1e0b1727 Phil Davis
1142 ff4e29fb stilez
	// Errors generated by user code (diag_commands.php) are identified by path and not added to notices
1143 2568e151 Christian McDonald
	if ($error !== NULL && !preg_match('|^' . preg_quote(g_get('tmp_path_user_code')) . '/[^/]{1,16}$|', $error['file'])) {
1144 ae346354 PiBa-NL
		if (in_array($error['type'], array(E_ERROR, E_COMPILE_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR))) {
1145 be2d7eb7 Chris Buechler
			$errorstr = "PHP ERROR: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}";
1146 b3f2f476 PiBa-NL
			print($errorstr);
1147
			log_error($errorstr);
1148 ae346354 PiBa-NL
			file_notice("phperror", $errorstr, 'PHP errors');
1149 6c07db48 Phil Davis
		} else if ($error['type'] != E_NOTICE) {
1150 b3f2f476 PiBa-NL
			$errorstr = "PHP WARNING: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}";
1151 e8e494f3 Chris Buechler
			// XXX: comment out for now, should re-enable post-2.2
1152
			//print($errorstr);
1153
			//log_error($errorstr);
1154 ae346354 PiBa-NL
			//file_notice("phpwarning", $errorstr, 'PHP warning');
1155 be2d7eb7 Chris Buechler
		}
1156
	}
1157
1158 1e0b1727 Phil Davis
	if (isset($FilterIfList)) {
1159 00e55088 Ermal
		unset($FilterIfList);
1160 1e0b1727 Phil Davis
	}
1161 00e55088 Ermal
1162 1e0b1727 Phil Davis
	if (isset($GatewaysList)) {
1163 00e55088 Ermal
		unset($GatewaysList);
1164 1e0b1727 Phil Davis
	}
1165 00e55088 Ermal
1166
	/* Used for the hostname dns resolver */
1167 1e0b1727 Phil Davis
	if (isset($filterdns)) {
1168 00e55088 Ermal
		unset($filterdns);
1169 1e0b1727 Phil Davis
	}
1170 00e55088 Ermal
1171
	/* Used for aliases and interface macros */
1172 1e0b1727 Phil Davis
	if (isset($aliases)) {
1173 00e55088 Ermal
		unset($aliases);
1174 1e0b1727 Phil Davis
	}
1175
	if (isset($aliastable)) {
1176 00e55088 Ermal
		unset($aliastable);
1177 1e0b1727 Phil Davis
	}
1178 00e55088 Ermal
1179
	unset($config);
1180
}
1181
1182 dd7d7022 Christian McDonald
/*
1183
 * Same semantics as init_config_arr(), but with the new
1184
 * path string interface.
1185
 */
1186
function config_init_path(string $path) {
1187
	global $config;
1188
	array_init_path($config, $path);
1189
}
1190
1191
/* 
1192
 * Notice: Use config_init_path() instead, if you must...
1193
 *
1194
 * This is retained for compatibility with older code
1195
 *
1196
 * Initialize a config array multiple levels deep only if unset
1197 65b5efa7 jim-p
 * Pass it an array of keys to test and create
1198
 * init_config_arr(array('virtualip', 'vip'));
1199
 */
1200 dd7d7022 Christian McDonald
function init_config_arr($keys) {
1201
	// just translate the old signature to the new one
1202
	config_init_path(implode('/', $keys));
1203 65b5efa7 jim-p
}
1204
1205 92abdaf0 Reid Linnemann
/**
1206 c4117e83 Reid Linnemann
 * Return a value specified by path in the config, if it exists.
1207 92abdaf0 Reid Linnemann
 * @param $path string path with '/' separators
1208
 * @param $default mixed value to return if the path is not found
1209 1333725e Reid Linnemann
 * @returns mixed value at path or $default if the path does not exist or if the
1210 5538e593 Reid Linnemann
 *          path keys an empty string and $default is non-null
1211 92abdaf0 Reid Linnemann
 */
1212
function config_get_path(string $path, $default = null) {
1213
	global $config;
1214 fab98cb6 Reid Linnemann
	return(array_get_path($config, $path, $default));
1215 92abdaf0 Reid Linnemann
}
1216
1217
/**
1218 c4117e83 Reid Linnemann
 * Set a value by path in the config, creating arrays for intermediary keys as
1219
 * necessary. If the path cannot be reached because an intermediary exists but
1220
 * is not empty or an array, return $default.
1221 92abdaf0 Reid Linnemann
 * @param $path string path with '/' separators
1222
 * @param $val mixed 
1223
 * @param $default mixed value to return if the path is not found
1224
 * @returns mixed $val or $default if the path prefix does not exist
1225
 */
1226
function config_set_path(string $path, $value, $default = null) {
1227
	global $config;
1228 eec3ca7f Reid Linnemann
	return (array_set_path($config, $path, $value, $default));
1229 92abdaf0 Reid Linnemann
}
1230
1231 03215791 Reid Linnemann
/**
1232 c4117e83 Reid Linnemann
 * Determine whether a path in the config has a non-null value keyed by
1233
 * $enable_key. Some parts of the config historically identify services as
1234
 * enabled by having a key to a non-null value named 'enable', and checking it
1235
 * with isset(). This can be counter-intuitive as isset() will return true if
1236
 * the array element is any non-null value that evaluates to false.
1237 03215791 Reid Linnemann
 * @param $path string path with '/' separators
1238
 * @param $enable_key string an optional alternative key value for the enable key
1239
 * @returns bool true if $enable_key exists in the array at $path, and has a
1240 c4117e83 Reid Linnemann
 * non-null value, otherwise false.
1241 03215791 Reid Linnemann
 */
1242
function config_path_enabled(string $path, $enable_key = "enable") {
1243 fab98cb6 Reid Linnemann
	global $config;
1244
	return (array_path_enabled($config, $path, $enable_key));
1245 03215791 Reid Linnemann
}
1246
1247 eec3ca7f Reid Linnemann
/**
1248
 * Remove a key from the config by path
1249
 * @param $path string path with '/' separators
1250
 * @returns array copy of the removed value or null
1251
 */
1252
function config_del_path(string $path) {
1253
	global $config;
1254
	return (array_del_path($config, $path));
1255
}
1256 00e55088 Ermal
register_shutdown_function('pfSense_clear_globals');
1257
1258 09221bc3 Renato Botelho
?>