Project

General

Profile

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