Project

General

Profile

Download (24.9 KB) Statistics
| Branch: | Tag: | Revision:
1 12df7edc Erik
<?php
2
/****h* pfSense/config
3
 * NAME
4 032c40c7 Scott Ullrich
 *   config.lib.inc - Functions to manipulate config.xml
5 12df7edc Erik
 * DESCRIPTION
6
 *   This include contains various config.xml specific functions.
7
 * HISTORY
8
 * $Id$
9
 ******
10
11
	config.lib.inc
12
	Ported from config.inc by Erik Kristensen
13 032c40c7 Scott Ullrich
	Copyright (C) 2004-2010 Scott Ullrich
14 12df7edc Erik
	All rights reserved.
15
16
	originally part of m0n0wall (http://m0n0.ch/wall)
17
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
18
	All rights reserved.
19
20
	Redistribution and use in source and binary forms, with or without
21
	modification, are permitted provided that the following conditions are met:
22
23
	1. Redistributions of source code must retain the above copyright notice,
24
	   this list of conditions and the following disclaimer.
25
26
	2. Redistributions in binary form must reproduce the above copyright
27
	   notice, this list of conditions and the following disclaimer in the
28
	   documentation and/or other materials provided with the distribution.
29
30
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
	POSSIBILITY OF SUCH DAMAGE.
40
41
42 5ba5a8de Scott Ullrich
	pfSense_BUILDER_BINARIES:	/sbin/mount	/sbin/sysctl	/sbin/umount	/sbin/halt	/sbin/fsck
43 12df7edc Erik
	pfSense_MODULE:	config
44
*/
45
46
/****f* config/encrypted_configxml
47
 * NAME
48
 *   encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock.
49
 * INPUTS
50
 *   None
51
 * RESULT
52
 *   $config 	- rewrites config.xml without encryption
53
 ******/
54
function encrypted_configxml() {
55
	global $g, $config;
56 02e9880e Ermal
57
	if (!file_exists($g['conf_path'] . "/config.xml"))
58
		return;
59
60
	if (!$g['booting'])
61
		return;
62
63
	$configtxt = file_get_contents($g['conf_path'] . "/config.xml");			
64
	if(tagfile_deformat($configtxt, $configtxt, "config.xml")) {
65
		$fp = fopen('php://stdin', 'r');
66
		$data = "";
67
		echo "\n\n*** Encrypted config.xml detected ***\n";
68
		while($data == "") {
69
			echo "\nEnter the password to decrypt config.xml: ";
70
			$decrypt_password = chop(fgets($fp));
71
			$data = decrypt_data($configtxt, $decrypt_password);
72
			if(!strstr($data, "<pfsense>"))
73 12df7edc Erik
				$data = "";
74 02e9880e Ermal
			if($data) {
75
				$fd = fopen($g['conf_path'] . "/config.xml.tmp", "w");
76
				fwrite($fd, $data);
77
				fclose($fd);
78
				exec("/bin/mv {$g['conf_path']}/config.xml.tmp {$g['conf_path']}/config.xml");
79
				echo "\nConfig.xml unlocked.\n";
80
				fclose($fp);
81
			} else {
82
				echo "\nInvalid password entered.  Please try again.\n";
83 12df7edc Erik
			}
84
		}
85
	}
86
}
87
88
/****f* config/parse_config
89
 * NAME
90
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
91
 * INPUTS
92
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
93
 * RESULT
94
 *   $config      - array containing all configuration variables
95
 ******/
96 1295e769 Scott Ullrich
function parse_config($parse = false) {
97 4e9a3392 Scott Ullrich
	global $g, $config_parsed, $config_extra;
98 02e9880e Ermal
99 12df7edc Erik
	$lockkey = lock('config');
100 0af381c2 Scott Ullrich
	$config_parsed = false;
101 02e9880e Ermal
102 12df7edc Erik
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
103
		$last_backup = discover_last_backup();
104
		if($last_backup) {
105
			log_error("No config.xml found, attempting last known config restore.");
106
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
107
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
108
		} else {
109
			unlock($lockkey);
110
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
111
		}
112
	}
113 02e9880e Ermal
114
	if($g['booting'])
115
		echo ".";
116
117 12df7edc Erik
	// Check for encrypted config.xml
118
	encrypted_configxml();
119 02e9880e Ermal
120 12df7edc Erik
	if(!$parse) {
121 02e9880e Ermal
		if (file_exists($g['tmp_path'] . '/config.cache')) {
122 12df7edc Erik
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
123 02e9880e Ermal
			if (is_null($config))
124
				$parse = true;
125
		} else
126
			$parse = true;
127
	}
128
	if ($parse == true) {
129 12df7edc Erik
		if(!file_exists($g['conf_path'] . "/config.xml")) {
130 02e9880e Ermal
			if($g['booting'])
131
				echo ".";
132 12df7edc Erik
			log_error("No config.xml found, attempting last known config restore.");
133
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
134
			$last_backup = discover_last_backup();
135
			if ($last_backup)
136
				restore_backup("/cf/conf/backup/{$last_backup}");
137 50cafcf3 Ermal
			else {
138 12df7edc Erik
				log_error("Could not restore config.xml.");
139 50cafcf3 Ermal
				unlock($lockkey);
140
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
141
			}
142 12df7edc Erik
		}
143 990d7c03 Erik Fonnesbeck
		$config = parse_xml_config($g['conf_path'] . '/config.xml', array($g['xml_rootobj'], 'pfsense'));
144 02e9880e Ermal
		if($config == -1) {
145 12df7edc Erik
			$last_backup = discover_last_backup();
146
			if ($last_backup)
147
				restore_backup("/cf/conf/backup/{$last_backup}");
148 50cafcf3 Ermal
			else {
149 12df7edc Erik
				log_error(gettext("Could not restore config.xml."));
150 50cafcf3 Ermal
				unlock($lockkey);
151
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
152
			}
153 12df7edc Erik
		}
154
		generate_config_cache($config);
155
	}
156 02e9880e Ermal
157
	if($g['booting'])
158
		echo ".";
159
160 12df7edc Erik
	$config_parsed = true;
161
	unlock($lockkey);
162
163 02e9880e Ermal
	alias_make_table($config);
164
165 12df7edc Erik
	return $config;
166
}
167
168
/****f* config/generate_config_cache
169
 * NAME
170
 *   generate_config_cache - Write serialized configuration to cache.
171
 * INPUTS
172
 *   $config	- array containing current firewall configuration
173
 * RESULT
174
 *   boolean	- true on completion
175
 ******/
176
function generate_config_cache($config) {
177 4e9a3392 Scott Ullrich
	global $g, $config_extra;
178 12df7edc Erik
179
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
180
	fwrite($configcache, serialize($config));
181
	fclose($configcache);
182 4e9a3392 Scott Ullrich
	unset($configcache);
183
	/* Used for config.extra.xml */
184
	if(file_exists($g['tmp_path'] . '/config.extra.cache') && $config_extra) {
185
		$configcacheextra = fopen($g['tmp_path'] . '/config.extra.cache', "w");
186
		fwrite($configcacheextra, serialize($config_extra));
187
		fclose($configcacheextra);		
188
		unset($configcacheextra);
189
	}
190 12df7edc Erik
}
191
192
function discover_last_backup() {
193
        $backups = split("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
194
	$last_backup = "";
195
        foreach($backups as $backup)
196
        	if($backup)
197
	        	$last_backup = $backup;
198
199
        return $last_backup;
200
}
201
202
function restore_backup($file) {
203
	global $g;
204
205
	if (file_exists($file)) {
206
		conf_mount_rw();
207
		unlink_if_exists("{$g['tmp_path']}/config.cache");
208 e490f995 Ermal
		copy("$file","/cf/conf/config.xml");
209 0f806eca Erik Fonnesbeck
		disable_security_checks();
210 12df7edc Erik
		log_error("{$g['product_name']} is restoring the configuration $file");
211 b3405363 Scott Ullrich
		file_notice("config.xml", "{$g['product_name']} is restoring the configuration $file", "{$g['product_name']}Configurator", "");
212 12df7edc Erik
		conf_mount_ro();
213
	}
214
}
215
216
/****f* config/parse_config_bootup
217
 * NAME
218
 *   parse_config_bootup - Bootup-specific configuration checks.
219
 * RESULT
220
 *   null
221
 ******/
222
function parse_config_bootup() {
223 50cafcf3 Ermal
	global $config, $g;
224 12df7edc Erik
225 02e9880e Ermal
	if($g['booting'])
226
		echo ".";
227 12df7edc Erik
228
	$lockkey = lock('config');
229 50cafcf3 Ermal
	if (!file_exists("{$g['conf_path']}/config.xml")) {
230
		if ($g['booting']) {
231
			if (strstr($g['platform'], "cdrom")) {
232
				/* try copying the default config. to the floppy */
233
				echo "Resetting factory defaults...\n";
234
				reset_factory_defaults(true);
235
				if (!file_exists("{$g['conf_path']}/config.xml")) {
236
					echo "No XML configuration file found - using factory defaults.\n";
237
					echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
238
					echo "file is inserted. If it isn't, your configuration changes will be lost\n";
239
					echo "on reboot.\n";
240 12df7edc Erik
				}
241
			} else {
242 50cafcf3 Ermal
				$last_backup = discover_last_backup();
243
				if($last_backup) {
244
					log_error("No config.xml found, attempting last known config restore.");
245
					file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
246
					restore_backup("/cf/conf/backup/{$last_backup}");
247
				}
248
				if(!file_exists("{$g['conf_path']}/config.xml")) {
249
					echo "XML configuration file not found.  {$g['product_name']} cannot continue booting.\n";
250 02e9880e Ermal
					unlock($lockkey);
251 50cafcf3 Ermal
					mwexec("/sbin/halt");
252
					exit;
253
				}
254
				log_error("Last known config found and restored.  Please double check your configuration file for accuracy.");
255
				file_notice("config.xml", "Last known config found and restored.  Please double check your configuration file for accuracy.", "pfSenseConfigurator", "");
256 12df7edc Erik
			}
257 50cafcf3 Ermal
		} else {
258
			unlock($lockkey);
259
			exit(0);
260 12df7edc Erik
		}
261
	}
262 50cafcf3 Ermal
263 12df7edc Erik
	if (filesize("{$g['conf_path']}/config.xml") == 0) {
264
		$last_backup = discover_last_backup();
265
		if($last_backup) {
266
			log_error("No config.xml found, attempting last known config restore.");
267
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
268
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
269
		} else {
270
			unlock($lockkey);
271
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
272
		}
273
	}
274
	unlock($lockkey);
275
	parse_config(true);
276
277
	if ((float)$config['version'] > (float)$g['latest_config']) {
278
		echo <<<EOD
279
280
281
*******************************************************************************
282
* WARNING!                                                                    *
283
* The current configuration has been created with a newer version of {$g['product_name']}  *
284
* than this one! This can lead to serious misbehavior and even security       *
285
* holes! You are urged to either upgrade to a newer version of {$g['product_name']} or     *
286
* revert to the default configuration immediately!                            *
287
*******************************************************************************
288
289
290
EOD;
291
		}
292
293
	/* make alias table (for faster lookups) */
294
	alias_make_table($config);
295
}
296
297
/****f* config/conf_mount_rw
298
 * NAME
299
 *   conf_mount_rw - Mount filesystems read/write.
300
 * RESULT
301
 *   null
302
 ******/
303
/* mount flash card read/write */
304 63e18082 jim-p
function conf_mount_rw() {
305 12df7edc Erik
	global $g;
306
307
	/* do not mount on cdrom platform */
308
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
309
		return;
310 a45e27ba Ermal
311
	if (refcount_reference(1000) > 1)
312 12df7edc Erik
		return;
313
314 e8567e89 jim-p
	$status = mwexec("/sbin/mount -u -w -o sync,noatime {$g['cf_path']}");
315 12df7edc Erik
	if($status <> 0) {
316
		if($g['booting'])
317
			echo "Disk is dirty.  Running fsck -y\n";
318
		mwexec("/sbin/fsck -y {$g['cf_path']}");
319 e8567e89 jim-p
		$status = mwexec("/sbin/mount -u -w -o sync,noatime {$g['cf_path']}");
320 12df7edc Erik
	}
321
322
	/*    if the platform is soekris or wrap or pfSense, lets mount the
323
	 *    compact flash cards root.
324 63e18082 jim-p
         */
325 e8567e89 jim-p
	$status = mwexec("/sbin/mount -u -w -o sync,noatime /");
326 a45e27ba Ermal
	/* we could not mount this correctly.  kick off fsck */
327
	if($status <> 0) {
328
		log_error("File system is dirty.  Launching FSCK for /");
329
		mwexec("/sbin/fsck -y /");
330 e8567e89 jim-p
		$status = mwexec("/sbin/mount -u -w -o sync,noatime /");
331 12df7edc Erik
	}
332
	
333
	mark_subsystem_dirty('mount');
334
}
335
336
/****f* config/conf_mount_ro
337
 * NAME
338
 *   conf_mount_ro - Mount filesystems readonly.
339
 * RESULT
340
 *   null
341
 ******/
342 63e18082 jim-p
function conf_mount_ro() {
343 12df7edc Erik
	global $g;
344
345 23f0ca50 Ermal Lu?i
	/* do not umount on cdrom or pfSense platforms */
346
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
347
		return;
348
349 63e18082 jim-p
	if($g['booting'])
350 52f4c092 Scott Ullrich
		return;
351
352 a45e27ba Ermal
	if (refcount_unreference(1000) > 0)
353 12df7edc Erik
		return;
354
355
	clear_subsystem_dirty('mount');
356
	/* sync data, then force a remount of /cf */
357 5ba5a8de Scott Ullrich
	pfSense_sync();
358 e8567e89 jim-p
	mwexec("/sbin/mount -u -r -f -o sync,noatime {$g['cf_path']}");
359
	mwexec("/sbin/mount -u -r -f -o sync,noatime /");
360 12df7edc Erik
}
361
362
/****f* config/convert_config
363
 * NAME
364
 *   convert_config - Attempt to update config.xml.
365
 * DESCRIPTION
366
 *   convert_config() reads the current global configuration
367
 *   and attempts to convert it to conform to the latest
368
 *   config.xml version. This allows major formatting changes
369
 *   to be made with a minimum of breakage.
370
 * RESULT
371
 *   null
372
 ******/
373
/* convert configuration, if necessary */
374
function convert_config() {
375
	global $config, $g;
376
	$now = date("H:i:s");
377
	log_error("Start Configuration upgrade at $now, set execution timeout to 15 minutes");
378 59cfe65d Ermal
	//ini_set("max_execution_time", "900");
379 12df7edc Erik
380
	/* special case upgrades */
381
	/* fix every minute crontab bogons entry */
382
	$cron_item_count = count($config['cron']['item']);
383
	for($x=0; $x<$cron_item_count; $x++) {
384
		if(stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
385
			if($config['cron']['item'][$x]['hour'] == "*" ) {
386
		        $config['cron']['item'][$x]['hour'] = "3";
387
		 		write_config("Updated bogon update frequency to 3am");
388
		 		log_error("Updated bogon update frequency to 3am");
389
		 	}       
390
		}
391
	}
392
	if ($config['version'] == $g['latest_config'])
393
		return;		/* already at latest version */
394
395
	// Save off config version
396
	$prev_version = $config['version'];
397
	
398 b96cad97 Seth Mos
	include_once('auth.inc');
399 12df7edc Erik
	include_once('upgrade_config.inc');
400 e58da189 Ermal
	if (file_exists("/etc/inc/upgrade_config_custom.inc"))
401
		include_once("upgrade_config_custom.inc");
402 12df7edc Erik
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
403
	while ($config['version'] < $g['latest_config']) {
404
		$cur = $config['version'] * 10;
405
		$next = $cur + 1;
406
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
407 cb0e3f8e Ermal
		if (function_exists($migration_function))
408
			$migration_function();
409 e58da189 Ermal
		$migration_function = "{$migration_function}_custom";
410
		if (function_exists($migration_function))
411
			$migration_function();
412 12df7edc Erik
		$config['version'] = sprintf('%.1f', $next / 10);
413 92cf9fcd sullrich
		if($g['booting'])
414
			echo ".";
415 12df7edc Erik
	}
416
417
	$now = date("H:i:s");
418
	log_error("Ended Configuration upgrade at $now");
419
420
	if ($prev_version != $config['version'])
421
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
422
}
423
424 ddd42db3 Ermal Lu?i
/****f* config/safe_write_file
425
 * NAME
426
 *   safe_write_file - Write a file out atomically
427
 * DESCRIPTION
428
 *   safe_write_file() Writes a file out atomically by first writing to a
429
 *   temporary file of the same name but ending with the pid of the current
430
 *   process, them renaming the temporary file over the original.
431
 * INPUTS
432
 *   $filename  - string containing the filename of the file to write
433
 *   $content   - string containing the file content to write to file
434
 *   $force_binary      - boolean denoting whether we should force binary
435
 *   mode writing.
436
 * RESULT
437
 *   boolean - true if successful, false if not
438
 ******/
439
function safe_write_file($file, $content, $force_binary) {
440 628d1548 Ermal
	$tmp_file = $file . "." . getmypid();
441
	$write_mode = $force_binary ? "wb" : "w";
442 ddd42db3 Ermal Lu?i
443 628d1548 Ermal
	$fd = fopen($tmp_file, $write_mode);
444
	if (!$fd) {
445
		// Unable to open temporary file for writing
446
		return false;
447 ddd42db3 Ermal Lu?i
        }
448 628d1548 Ermal
	if (!fwrite($fd, $content)) {
449
		// Unable to write to temporary file
450 00bc5bcc Scott Ullrich
		fclose($fd);
451 628d1548 Ermal
		return false;
452
	}
453
	fflush($fd);
454
	fclose($fd);
455 ddd42db3 Ermal Lu?i
456 628d1548 Ermal
	if (!rename($tmp_file, $file)) {
457
		// Unable to move temporary file to original
458
		@unlink($tmp_file);
459
		return false;
460
	}
461 00bc5bcc Scott Ullrich
462 628d1548 Ermal
	// Sync file before returning
463
	pfSense_sync();
464 00bc5bcc Scott Ullrich
465 628d1548 Ermal
	return true;
466 ddd42db3 Ermal Lu?i
}
467
468 12df7edc Erik
/****f* config/write_config
469
 * NAME
470
 *   write_config - Backup and write the firewall configuration.
471
 * DESCRIPTION
472
 *   write_config() handles backing up the current configuration,
473
 *   applying changes, and regenerating the configuration cache.
474
 * INPUTS
475
 *   $desc	- string containing the a description of configuration changes
476
 *   $backup	- boolean: do not back up current configuration if false.
477
 * RESULT
478
 *   null
479
 ******/
480
/* save the system configuration */
481
function write_config($desc="Unknown", $backup = true) {
482
	global $config, $g;
483
484 027b8057 Erik Fonnesbeck
	/* TODO: Not sure what this was added for; commenting out
485
	 *       for now, since it was preventing config saving. */
486
	// $config = parse_config(true, false, false);
487 4e9a3392 Scott Ullrich
	
488 a8f9f07e jim-p
	/* Comment this check out for now. There aren't any current issues that
489
	 *   make this problematic, and it makes users think there is a problem
490
	 *   when one doesn't really exist.
491 fa09d1b8 jim-p
	if($g['booting'])
492 12df7edc Erik
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
493 a8f9f07e jim-p
	*/
494 12df7edc Erik
495 ba4f6e1d jim-p
	$username = empty($_SESSION["Username"]) ? "(system)" : $_SESSION['Username'];
496
497 12df7edc Erik
	if($backup)
498
		backup_config();
499
500 5af3a589 Ermal
	if (!is_array($config['revision']))
501
		$config['revision'] = array();
502
503 12df7edc Erik
	if (time() > mktime(0, 0, 0, 9, 1, 2004))       /* make sure the clock settings are plausible */
504 541989d5 Ermal
		$config['revision']['time'] = time();
505 12df7edc Erik
506
	/* Log the running script so it's not entirely unlogged what changed */
507 42739c1c Ermal Lu?i
	if ($desc == "Unknown")
508 4d52a9b9 jim-p
		$desc = "{$_SERVER['SCRIPT_NAME']} made unknown change";
509 12df7edc Erik
510 ba4f6e1d jim-p
	$config['revision']['description'] = "{$username}: " . $desc;
511
	$config['revision']['username'] = $username;
512 12df7edc Erik
513 b6c34bfc Ermal
	conf_mount_rw();
514
	$lockkey = lock('config', LOCK_EX);
515 12df7edc Erik
516
	/* generate configuration XML */
517
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
518
519 41bf8e8e Scott Ullrich
	/* write new configuration */
520
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
521 12df7edc Erik
		log_error("WARNING: Config contents could not be save. Could not open file!");
522
		unlock($lockkey);
523 07f1ca1d Ermal
		file_notice("config.xml", "Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
524 541989d5 Ermal
		return -1;
525 e5977136 Scott Ullrich
	}
526 41bf8e8e Scott Ullrich
	
527 12df7edc Erik
	if($g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
528
		cleanup_backupcache(5, true);
529
	} else {
530
		cleanup_backupcache(30, true);
531
	}
532
533
	/* re-read configuration */
534 541989d5 Ermal
	/* NOTE: We assume that the file can be parsed since we wrote it. */
535 12df7edc Erik
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
536 e490f995 Ermal
	if ($config == -1) {
537
		$last_backup = discover_last_backup();
538
		if ($last_backup)
539
			restore_backup("/cf/conf/backup/{$last_backup}");
540
		else
541
			log_error(gettext("Could not restore config.xml."));
542
	} else
543
		generate_config_cache($config);
544 12df7edc Erik
545
	unlock($lockkey);
546
547
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
548 16b96ea6 Scott Ullrich
549 b6c34bfc Ermal
	/* tell kernel to sync fs data */
550
	conf_mount_ro();
551
552 12df7edc Erik
	/* sync carp entries to other firewalls */
553 16b96ea6 Scott Ullrich
	carp_sync_client();
554 12df7edc Erik
555
	if(is_dir("/usr/local/pkg/write_config")) {
556
		/* process packager manager custom rules */
557
		run_plugins("/usr/local/pkg/write_config/");
558
	}
559
560
	return $config;
561
}
562
563
/****f* config/reset_factory_defaults
564
 * NAME
565
 *   reset_factory_defaults - Reset the system to its default configuration.
566
 * RESULT
567
 *   integer	- indicates completion
568
 ******/
569
function reset_factory_defaults($lock = false) {
570
	global $g;
571
572
	conf_mount_rw();
573 b6c34bfc Ermal
	if (!$lock)
574
		$lockkey = lock('config', LOCK_EX);
575 12df7edc Erik
576
	/* create conf directory, if necessary */
577
	safe_mkdir("{$g['cf_conf_path']}");
578
579
	/* clear out /conf */
580
	$dh = opendir($g['conf_path']);
581
	while ($filename = readdir($dh)) {
582
		if (($filename != ".") && ($filename != "..")) {
583
			unlink_if_exists($g['conf_path'] . "/" . $filename);
584
		}
585
	}
586
	closedir($dh);
587
588
	/* copy default configuration */
589
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
590
591 0f806eca Erik Fonnesbeck
	disable_security_checks();
592
593 12df7edc Erik
	/* call the wizard */
594
	touch("/conf/trigger_initial_wizard");
595
	if (!$lock)
596
		unlock($lockkey);
597 b6c34bfc Ermal
	conf_mount_ro();
598 12df7edc Erik
599
	return 0;
600
}
601
602
function config_restore($conffile) {
603
	global $config, $g;
604
605
	if (!file_exists($conffile))
606
		return 1;
607
608
	backup_config();
609
610 f2087c85 Scott Ullrich
	conf_mount_rw();
611
	
612 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
613 12df7edc Erik
614
	unlink_if_exists("{$g['tmp_path']}/config.cache");
615 e490f995 Ermal
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
616 12df7edc Erik
617 0f806eca Erik Fonnesbeck
	disable_security_checks();
618
619 12df7edc Erik
	unlock($lockkey);
620
621
	$config = parse_config(true);
622
623
	conf_mount_ro();
624
625 e296b183 Ermal Lu?i
	write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
626
627 12df7edc Erik
	return 0;
628
}
629
630
function config_install($conffile) {
631
	global $config, $g;
632
633
	if (!file_exists($conffile))
634
		return 1;
635
636
	if (!config_validate("{$conffile}"))
637
		return 1;
638
639
	if($g['booting'] == true)
640
		echo "Installing configuration...\n";
641
	else
642
		log_error("Installing configuration ....");
643
644
	conf_mount_rw();
645 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
646 12df7edc Erik
647
	copy($conffile, "{$g['conf_path']}/config.xml");
648
649 0f806eca Erik Fonnesbeck
	disable_security_checks();
650
651 12df7edc Erik
	/* unlink cache file if it exists */
652
	if(file_exists("{$g['tmp_path']}/config.cache"))
653
		unlink("{$g['tmp_path']}/config.cache");
654
655
	unlock($lockkey);
656
	conf_mount_ro();
657
658
    return 0;
659
}
660
661 0f806eca Erik Fonnesbeck
/*
662
 * Disable security checks for DNS rebind and HTTP referrer until next time
663
 * they pass (or reboot), to aid in preventing accidental lockout when
664
 * restoring settings like hostname, domain, IP addresses, and settings
665
 * related to the DNS rebind and HTTP referrer checks.
666
 * Intended for use when restoring a configuration or directly
667
 * modifying config.xml without an unconditional reboot.
668
 */
669
function disable_security_checks() {
670
	global $g;
671
	touch("{$g['tmp_path']}/disable_security_checks");
672
}
673
674
/* Restores security checks.  Should be called after all succeed. */
675
function restore_security_checks() {
676
	global $g;
677
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
678
}
679
680
/* Returns status of security check temporary disable. */
681
function security_checks_disabled() {
682
	global $g;
683
	return file_exists("{$g['tmp_path']}/disable_security_checks");
684
}
685
686 12df7edc Erik
function config_validate($conffile) {
687
688
	global $g, $xmlerr;
689
690
	$xml_parser = xml_parser_create();
691
692
	if (!($fp = fopen($conffile, "r"))) {
693
		$xmlerr = "XML error: unable to open file";
694
		return false;
695
	}
696
697
	while ($data = fread($fp, 4096)) {
698
		if (!xml_parse($xml_parser, $data, feof($fp))) {
699
			$xmlerr = sprintf("%s at line %d",
700
						xml_error_string(xml_get_error_code($xml_parser)),
701
						xml_get_current_line_number($xml_parser));
702
			return false;
703
		}
704
	}
705
	xml_parser_free($xml_parser);
706
707
	fclose($fp);
708
709
	return true;
710
}
711
712
function cleanup_backupcache($revisions = 30, $lock = false) {
713
	global $g;
714
	$i = false;
715
	
716
	if (!$lock)
717
		$lockkey = lock('config');
718 cd25a2b2 jim-p
719
	conf_mount_rw();
720
721
	$backups = get_backups();
722
	if ($backups) {
723 12df7edc Erik
		$baktimes = $backups['versions'];
724
		unset($backups['versions']);
725 cd25a2b2 jim-p
	} else {
726
		$backups = array();
727
		$baktimes = array();
728
	}
729
	$newbaks = array();
730
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
731
	$tocache = array();
732 12df7edc Erik
733 cd25a2b2 jim-p
	foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
734
		if(filesize($backup) == 0) {
735
			unlink($backup);
736
			continue;
737
		}
738
		$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
739
		if(!in_array($tocheck, $baktimes)) {
740
			$i = true;
741
			if($g['booting'])
742
				echo ".";
743 990d7c03 Erik Fonnesbeck
			$newxml = parse_xml_config($backup, array($g['xml_rootobj'], 'pfsense'));
744 cd25a2b2 jim-p
			if($newxml == "-1") {
745
				log_error("The backup cache file $backup is corrupted.  Unlinking.");
746
				unlink($backup);
747
				log_error("The backup cache file $backup is corrupted.  Unlinking.");
748
				continue;
749 12df7edc Erik
			}
750 cd25a2b2 jim-p
			if($newxml['revision']['description'] == "")
751
				$newxml['revision']['description'] = "Unknown";
752
			$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
753 12df7edc Erik
		}
754 cd25a2b2 jim-p
	}
755
	foreach($backups as $checkbak) {
756
		if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
757
			$newbaks[] = $checkbak;
758
		} else {
759
			$i = true;
760
			if($g['booting']) print " " . $tocheck . "r";
761
		}
762
	}
763
	foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);
764
	if(is_int($revisions) and (count($tocache) > $revisions)) {
765
		$toslice = array_slice(array_keys($tocache), 0, $revisions);
766
		foreach($toslice as $sliced)
767
			$newcache[$sliced] = $tocache[$sliced];
768
		foreach($tocache as $version => $versioninfo) {
769
			if(!in_array($version, array_keys($newcache))) {
770
				unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
771 1c42331b Scott Ullrich
				//if($g['booting']) print " " . $tocheck . "d";
772 12df7edc Erik
			}
773
		}
774 cd25a2b2 jim-p
		$tocache = $newcache;
775 12df7edc Erik
	}
776 cd25a2b2 jim-p
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
777
	fwrite($bakout, serialize($tocache));
778
	fclose($bakout);
779
	conf_mount_ro();
780
781 12df7edc Erik
	if (!$lock)
782
		unlock($lockkey);
783
}
784
785
function get_backups() {
786
	global $g;
787
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
788
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
789
		$bakvers = array_keys($confvers);
790
		$toreturn = array();
791
		sort($bakvers);
792
		// 	$bakvers = array_reverse($bakvers);
793
		foreach(array_reverse($bakvers) as $bakver)
794
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
795
	} else {
796
		return false;
797
	}
798
	$toreturn['versions'] = $bakvers;
799
	return $toreturn;
800
}
801
802
function backup_config() {
803
	global $config, $g;
804
805
	if($g['platform'] == "cdrom")
806
		return;
807
808
	conf_mount_rw();
809
810
	/* Create backup directory if needed */
811
	safe_mkdir("{$g['cf_conf_path']}/backup");
812
813
    if($config['revision']['time'] == "") {
814
            $baktime = 0;
815
    } else {
816
            $baktime = $config['revision']['time'];
817
    }
818
    if($config['revision']['description'] == "") {
819
            $bakdesc = "Unknown";
820
    } else {
821
            $bakdesc = $config['revision']['description'];
822
    }
823
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
824
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
825
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
826
    } else {
827
            $backupcache = array();
828
    }
829
    $backupcache[$baktime] = array('description' => $bakdesc);
830
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
831
    fwrite($bakout, serialize($backupcache));
832
    fclose($bakout);
833
834
	conf_mount_ro();
835
836
	return true;
837
}
838
839
function set_device_perms() {
840
	$devices = array(
841 573c9548 Ermal
		'pf'	=> array(	'user'	=> 'root',
842 12df7edc Erik
					'group'	=> 'proxy',
843
					'mode'	=> 0660),
844
		);
845
846
	foreach ($devices as $name => $attr) {
847
		$path = "/dev/$name";
848
		if (file_exists($path)) {
849
			chown($path, $attr['user']);
850
			chgrp($path, $attr['group']);
851
			chmod($path, $attr['mode']);
852
		}
853
	}
854
}
855
856 63e18082 jim-p
?>