Project

General

Profile

Download (26.3 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 9d3d8d00 Vinicius Coque
				echo "\n" . gettext("Config.xml unlocked.") . "\n";
80 02e9880e Ermal
				fclose($fp);
81
			} else {
82 9d3d8d00 Vinicius Coque
				echo "\n" . gettext("Invalid 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 4e038d31 Carlos Eduardo Ramos
			log_error(gettext("No config.xml found, attempting last known config restore."));
106
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
107 12df7edc Erik
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
108
		} else {
109
			unlock($lockkey);
110 4e038d31 Carlos Eduardo Ramos
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
111 12df7edc Erik
		}
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 4e038d31 Carlos Eduardo Ramos
				log_error(gettext("Could not restore config.xml."));
139 50cafcf3 Ermal
				unlock($lockkey);
140 4816e5ca Renato Botelho
				die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
141 50cafcf3 Ermal
			}
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 cfbfd941 smos
        $backups = explode("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
194 12df7edc Erik
	$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 addc0439 Renato Botelho
		log_error(sprintf(gettext('%1$s is restoring the configuration %2$s'), $g['product_name'], $file));
211
		file_notice("config.xml", sprintf(gettext('%1$s is restoring the configuration %2$s'), $g['product_name'], $file), "pfSenseConfigurator", "");
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 4816e5ca Renato Botelho
				echo gettext("Resetting factory defaults...") . "\n";
234 50cafcf3 Ermal
				reset_factory_defaults(true);
235
				if (!file_exists("{$g['conf_path']}/config.xml")) {
236 4816e5ca Renato Botelho
					echo gettext("No XML configuration file found - using factory defaults.\n" .
237
								 "Make sure that the configuration floppy disk with the conf/config.xml\n" .
238
								 "file is inserted. If it isn't, your configuration changes will be lost\n" .
239
								 "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 4816e5ca Renato Botelho
					file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
246 50cafcf3 Ermal
					restore_backup("/cf/conf/backup/{$last_backup}");
247
				}
248
				if(!file_exists("{$g['conf_path']}/config.xml")) {
249 4816e5ca Renato Botelho
					echo sprintf(gettext("XML configuration file not found.  %s cannot continue booting."), $g['product_name']) . "\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 4816e5ca Renato Botelho
				file_notice("config.xml", gettext("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 4e038d31 Carlos Eduardo Ramos
			log_error(gettext("No config.xml found, attempting last known config restore."));
267
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
268 12df7edc Erik
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
269
		} else {
270
			unlock($lockkey);
271 4e038d31 Carlos Eduardo Ramos
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
272 12df7edc Erik
		}
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 4e038d31 Carlos Eduardo Ramos
			echo gettext("Disk is dirty.  Running fsck -y") . "\n";
318 12df7edc Erik
		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 4e038d31 Carlos Eduardo Ramos
		log_error(gettext("File system is dirty.  Launching FSCK for /"));
329 a45e27ba Ermal
		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 2de8d745 jim-p
	/* Do not trust $g['platform'] since this can be clobbered during factory reset. */
346
	$platform = trim(file_get_contents("/etc/platform"));
347 23f0ca50 Ermal Lu?i
	/* do not umount on cdrom or pfSense platforms */
348 2de8d745 jim-p
	if($platform == "cdrom" or $platform == "pfSense")
349 23f0ca50 Ermal Lu?i
		return;
350
351 e15e9c6b Ermal
	if (refcount_unreference(1000) > 0)
352 52f4c092 Scott Ullrich
		return;
353
354 e15e9c6b Ermal
	if($g['booting'])
355 12df7edc Erik
		return;
356
357
	clear_subsystem_dirty('mount');
358
	/* sync data, then force a remount of /cf */
359 5ba5a8de Scott Ullrich
	pfSense_sync();
360 e8567e89 jim-p
	mwexec("/sbin/mount -u -r -f -o sync,noatime {$g['cf_path']}");
361
	mwexec("/sbin/mount -u -r -f -o sync,noatime /");
362 12df7edc Erik
}
363
364
/****f* config/convert_config
365
 * NAME
366
 *   convert_config - Attempt to update config.xml.
367
 * DESCRIPTION
368
 *   convert_config() reads the current global configuration
369
 *   and attempts to convert it to conform to the latest
370
 *   config.xml version. This allows major formatting changes
371
 *   to be made with a minimum of breakage.
372
 * RESULT
373
 *   null
374
 ******/
375
/* convert configuration, if necessary */
376
function convert_config() {
377
	global $config, $g;
378
	$now = date("H:i:s");
379 4e038d31 Carlos Eduardo Ramos
	log_error(sprintf(gettext("Start Configuration upgrade at %s, set execution timeout to 15 minutes"), $now));
380 59cfe65d Ermal
	//ini_set("max_execution_time", "900");
381 12df7edc Erik
382
	/* special case upgrades */
383
	/* fix every minute crontab bogons entry */
384
	$cron_item_count = count($config['cron']['item']);
385
	for($x=0; $x<$cron_item_count; $x++) {
386
		if(stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
387
			if($config['cron']['item'][$x]['hour'] == "*" ) {
388
		        $config['cron']['item'][$x]['hour'] = "3";
389 4e038d31 Carlos Eduardo Ramos
		 		write_config(gettext("Updated bogon update frequency to 3am"));
390
		 		log_error(gettext("Updated bogon update frequency to 3am"));
391 12df7edc Erik
		 	}       
392
		}
393
	}
394
	if ($config['version'] == $g['latest_config'])
395
		return;		/* already at latest version */
396
397
	// Save off config version
398
	$prev_version = $config['version'];
399
	
400 b96cad97 Seth Mos
	include_once('auth.inc');
401 12df7edc Erik
	include_once('upgrade_config.inc');
402 e58da189 Ermal
	if (file_exists("/etc/inc/upgrade_config_custom.inc"))
403
		include_once("upgrade_config_custom.inc");
404 12df7edc Erik
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
405
	while ($config['version'] < $g['latest_config']) {
406
		$cur = $config['version'] * 10;
407
		$next = $cur + 1;
408
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
409 cb0e3f8e Ermal
		if (function_exists($migration_function))
410
			$migration_function();
411 e58da189 Ermal
		$migration_function = "{$migration_function}_custom";
412
		if (function_exists($migration_function))
413
			$migration_function();
414 12df7edc Erik
		$config['version'] = sprintf('%.1f', $next / 10);
415 92cf9fcd sullrich
		if($g['booting'])
416
			echo ".";
417 12df7edc Erik
	}
418
419
	$now = date("H:i:s");
420 4e038d31 Carlos Eduardo Ramos
	log_error(sprintf(gettext("Ended Configuration upgrade at %s"), $now));
421 12df7edc Erik
422
	if ($prev_version != $config['version'])
423 addc0439 Renato Botelho
		write_config(sprintf(gettext('Upgraded config version level from %1$s to %2$s'), $prev_version, $config['version']));
424 12df7edc Erik
}
425
426 ddd42db3 Ermal Lu?i
/****f* config/safe_write_file
427
 * NAME
428
 *   safe_write_file - Write a file out atomically
429
 * DESCRIPTION
430
 *   safe_write_file() Writes a file out atomically by first writing to a
431
 *   temporary file of the same name but ending with the pid of the current
432
 *   process, them renaming the temporary file over the original.
433
 * INPUTS
434
 *   $filename  - string containing the filename of the file to write
435
 *   $content   - string containing the file content to write to file
436
 *   $force_binary      - boolean denoting whether we should force binary
437
 *   mode writing.
438
 * RESULT
439
 *   boolean - true if successful, false if not
440
 ******/
441
function safe_write_file($file, $content, $force_binary) {
442 628d1548 Ermal
	$tmp_file = $file . "." . getmypid();
443
	$write_mode = $force_binary ? "wb" : "w";
444 ddd42db3 Ermal Lu?i
445 628d1548 Ermal
	$fd = fopen($tmp_file, $write_mode);
446
	if (!$fd) {
447
		// Unable to open temporary file for writing
448
		return false;
449 ddd42db3 Ermal Lu?i
        }
450 628d1548 Ermal
	if (!fwrite($fd, $content)) {
451
		// Unable to write to temporary file
452 00bc5bcc Scott Ullrich
		fclose($fd);
453 628d1548 Ermal
		return false;
454
	}
455
	fflush($fd);
456
	fclose($fd);
457 ddd42db3 Ermal Lu?i
458 628d1548 Ermal
	if (!rename($tmp_file, $file)) {
459
		// Unable to move temporary file to original
460
		@unlink($tmp_file);
461
		return false;
462
	}
463 00bc5bcc Scott Ullrich
464 628d1548 Ermal
	// Sync file before returning
465
	pfSense_sync();
466 00bc5bcc Scott Ullrich
467 628d1548 Ermal
	return true;
468 ddd42db3 Ermal Lu?i
}
469
470 12df7edc Erik
/****f* config/write_config
471
 * NAME
472
 *   write_config - Backup and write the firewall configuration.
473
 * DESCRIPTION
474
 *   write_config() handles backing up the current configuration,
475
 *   applying changes, and regenerating the configuration cache.
476
 * INPUTS
477
 *   $desc	- string containing the a description of configuration changes
478
 *   $backup	- boolean: do not back up current configuration if false.
479
 * RESULT
480
 *   null
481
 ******/
482
/* save the system configuration */
483
function write_config($desc="Unknown", $backup = true) {
484
	global $config, $g;
485
486 027b8057 Erik Fonnesbeck
	/* TODO: Not sure what this was added for; commenting out
487
	 *       for now, since it was preventing config saving. */
488
	// $config = parse_config(true, false, false);
489 4e9a3392 Scott Ullrich
	
490 a8f9f07e jim-p
	/* Comment this check out for now. There aren't any current issues that
491
	 *   make this problematic, and it makes users think there is a problem
492
	 *   when one doesn't really exist.
493 fa09d1b8 jim-p
	if($g['booting'])
494 12df7edc Erik
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
495 a8f9f07e jim-p
	*/
496 12df7edc Erik
497 ba4f6e1d jim-p
	$username = empty($_SESSION["Username"]) ? "(system)" : $_SESSION['Username'];
498 6fd8fde2 jim-p
	if (!empty($_SERVER['REMOTE_ADDR']))
499 a9404381 jim-p
		$username .= '@' . $_SERVER['REMOTE_ADDR'];
500 12df7edc Erik
501
	if($backup)
502
		backup_config();
503
504 5af3a589 Ermal
	if (!is_array($config['revision']))
505
		$config['revision'] = array();
506
507 12df7edc Erik
	if (time() > mktime(0, 0, 0, 9, 1, 2004))       /* make sure the clock settings are plausible */
508 541989d5 Ermal
		$config['revision']['time'] = time();
509 12df7edc Erik
510
	/* Log the running script so it's not entirely unlogged what changed */
511 42739c1c Ermal Lu?i
	if ($desc == "Unknown")
512 4e038d31 Carlos Eduardo Ramos
		$desc = sprintf(gettext("%s made unknown change"), $_SERVER['SCRIPT_NAME']);
513 12df7edc Erik
514 ba4f6e1d jim-p
	$config['revision']['description'] = "{$username}: " . $desc;
515
	$config['revision']['username'] = $username;
516 12df7edc Erik
517 b6c34bfc Ermal
	conf_mount_rw();
518
	$lockkey = lock('config', LOCK_EX);
519 12df7edc Erik
520
	/* generate configuration XML */
521
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
522
523 41bf8e8e Scott Ullrich
	/* write new configuration */
524
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
525 4e038d31 Carlos Eduardo Ramos
		log_error(gettext("WARNING: Config contents could not be save. Could not open file!"));
526 12df7edc Erik
		unlock($lockkey);
527 4e038d31 Carlos Eduardo Ramos
		file_notice("config.xml", sprintf(gettext("Unable to open %s/config.xml for writing in write_config()%s"), $g['cf_conf_path'], "\n"));
528 541989d5 Ermal
		return -1;
529 e5977136 Scott Ullrich
	}
530 41bf8e8e Scott Ullrich
	
531 12df7edc Erik
	if($g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
532
		cleanup_backupcache(5, true);
533
	} else {
534
		cleanup_backupcache(30, true);
535
	}
536
537
	/* re-read configuration */
538 541989d5 Ermal
	/* NOTE: We assume that the file can be parsed since we wrote it. */
539 12df7edc Erik
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
540 e490f995 Ermal
	if ($config == -1) {
541 557300a7 jim-p
		copy("{$g['conf_path']}/config.xml", "{$g['conf_path']}/config.xml.bad");
542 e490f995 Ermal
		$last_backup = discover_last_backup();
543 557300a7 jim-p
		if ($last_backup) {
544 e490f995 Ermal
			restore_backup("/cf/conf/backup/{$last_backup}");
545 557300a7 jim-p
			$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
546
			if ($g['booting']) {
547
				echo "\n\n ************** WARNING **************";
548 6177fd92 jim-p
				echo "\n\n Configuration could not be validated. A previous configuration was restored. \n";
549
				echo "\n The failed configuration file has been saved as {$g['conf_path']}/config.xml.bad} \n\n";
550 557300a7 jim-p
			}
551
		} else
552 e490f995 Ermal
			log_error(gettext("Could not restore config.xml."));
553
	} else
554
		generate_config_cache($config);
555 12df7edc Erik
556
	unlock($lockkey);
557
558
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
559 16b96ea6 Scott Ullrich
560 b6c34bfc Ermal
	/* tell kernel to sync fs data */
561
	conf_mount_ro();
562
563 12df7edc Erik
	/* sync carp entries to other firewalls */
564 16b96ea6 Scott Ullrich
	carp_sync_client();
565 12df7edc Erik
566
	if(is_dir("/usr/local/pkg/write_config")) {
567
		/* process packager manager custom rules */
568
		run_plugins("/usr/local/pkg/write_config/");
569
	}
570
571
	return $config;
572
}
573
574
/****f* config/reset_factory_defaults
575
 * NAME
576
 *   reset_factory_defaults - Reset the system to its default configuration.
577
 * RESULT
578
 *   integer	- indicates completion
579
 ******/
580
function reset_factory_defaults($lock = false) {
581
	global $g;
582
583
	conf_mount_rw();
584 b6c34bfc Ermal
	if (!$lock)
585
		$lockkey = lock('config', LOCK_EX);
586 12df7edc Erik
587
	/* create conf directory, if necessary */
588
	safe_mkdir("{$g['cf_conf_path']}");
589
590
	/* clear out /conf */
591
	$dh = opendir($g['conf_path']);
592
	while ($filename = readdir($dh)) {
593
		if (($filename != ".") && ($filename != "..")) {
594
			unlink_if_exists($g['conf_path'] . "/" . $filename);
595
		}
596
	}
597
	closedir($dh);
598
599
	/* copy default configuration */
600
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
601
602 0f806eca Erik Fonnesbeck
	disable_security_checks();
603
604 12df7edc Erik
	/* call the wizard */
605
	touch("/conf/trigger_initial_wizard");
606
	if (!$lock)
607
		unlock($lockkey);
608 b6c34bfc Ermal
	conf_mount_ro();
609 673966e4 jim-p
	setup_serial_port();
610 12df7edc Erik
	return 0;
611
}
612
613
function config_restore($conffile) {
614
	global $config, $g;
615
616
	if (!file_exists($conffile))
617
		return 1;
618
619
	backup_config();
620
621 f2087c85 Scott Ullrich
	conf_mount_rw();
622
	
623 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
624 12df7edc Erik
625
	unlink_if_exists("{$g['tmp_path']}/config.cache");
626 e490f995 Ermal
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
627 12df7edc Erik
628 0f806eca Erik Fonnesbeck
	disable_security_checks();
629
630 12df7edc Erik
	unlock($lockkey);
631
632
	$config = parse_config(true);
633
634
	conf_mount_ro();
635
636 4e038d31 Carlos Eduardo Ramos
	write_config(gettext("Reverted to") . " " . array_pop(explode("/", $conffile)) . ".", false);
637 e296b183 Ermal Lu?i
638 12df7edc Erik
	return 0;
639
}
640
641
function config_install($conffile) {
642
	global $config, $g;
643
644
	if (!file_exists($conffile))
645
		return 1;
646
647
	if (!config_validate("{$conffile}"))
648
		return 1;
649
650
	if($g['booting'] == true)
651 4e038d31 Carlos Eduardo Ramos
		echo gettext("Installing configuration...") . "\n";
652 12df7edc Erik
	else
653 4e038d31 Carlos Eduardo Ramos
		log_error(gettext("Installing configuration ...."));
654 12df7edc Erik
655
	conf_mount_rw();
656 b6c34bfc Ermal
	$lockkey = lock('config', LOCK_EX);
657 12df7edc Erik
658
	copy($conffile, "{$g['conf_path']}/config.xml");
659
660 0f806eca Erik Fonnesbeck
	disable_security_checks();
661
662 12df7edc Erik
	/* unlink cache file if it exists */
663
	if(file_exists("{$g['tmp_path']}/config.cache"))
664
		unlink("{$g['tmp_path']}/config.cache");
665
666
	unlock($lockkey);
667
	conf_mount_ro();
668
669
    return 0;
670
}
671
672 0f806eca Erik Fonnesbeck
/*
673
 * Disable security checks for DNS rebind and HTTP referrer until next time
674
 * they pass (or reboot), to aid in preventing accidental lockout when
675
 * restoring settings like hostname, domain, IP addresses, and settings
676
 * related to the DNS rebind and HTTP referrer checks.
677
 * Intended for use when restoring a configuration or directly
678
 * modifying config.xml without an unconditional reboot.
679
 */
680
function disable_security_checks() {
681
	global $g;
682
	touch("{$g['tmp_path']}/disable_security_checks");
683
}
684
685
/* Restores security checks.  Should be called after all succeed. */
686
function restore_security_checks() {
687
	global $g;
688
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
689
}
690
691
/* Returns status of security check temporary disable. */
692
function security_checks_disabled() {
693
	global $g;
694
	return file_exists("{$g['tmp_path']}/disable_security_checks");
695
}
696
697 12df7edc Erik
function config_validate($conffile) {
698
699
	global $g, $xmlerr;
700
701
	$xml_parser = xml_parser_create();
702
703
	if (!($fp = fopen($conffile, "r"))) {
704 4e038d31 Carlos Eduardo Ramos
		$xmlerr = gettext("XML error: unable to open file");
705 12df7edc Erik
		return false;
706
	}
707
708
	while ($data = fread($fp, 4096)) {
709
		if (!xml_parse($xml_parser, $data, feof($fp))) {
710 addc0439 Renato Botelho
			$xmlerr = sprintf(gettext('%1$s at line %2$d'),
711 12df7edc Erik
						xml_error_string(xml_get_error_code($xml_parser)),
712
						xml_get_current_line_number($xml_parser));
713
			return false;
714
		}
715
	}
716
	xml_parser_free($xml_parser);
717
718
	fclose($fp);
719
720
	return true;
721
}
722
723
function cleanup_backupcache($revisions = 30, $lock = false) {
724
	global $g;
725
	$i = false;
726
	
727
	if (!$lock)
728
		$lockkey = lock('config');
729 cd25a2b2 jim-p
730
	conf_mount_rw();
731
732
	$backups = get_backups();
733
	if ($backups) {
734 12df7edc Erik
		$baktimes = $backups['versions'];
735
		unset($backups['versions']);
736 cd25a2b2 jim-p
	} else {
737
		$backups = array();
738
		$baktimes = array();
739
	}
740
	$newbaks = array();
741
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
742
	$tocache = array();
743 12df7edc Erik
744 cd25a2b2 jim-p
	foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
745
		if(filesize($backup) == 0) {
746
			unlink($backup);
747
			continue;
748
		}
749
		$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
750
		if(!in_array($tocheck, $baktimes)) {
751
			$i = true;
752
			if($g['booting'])
753
				echo ".";
754 990d7c03 Erik Fonnesbeck
			$newxml = parse_xml_config($backup, array($g['xml_rootobj'], 'pfsense'));
755 cd25a2b2 jim-p
			if($newxml == "-1") {
756 4e038d31 Carlos Eduardo Ramos
				log_error(sprintf(gettext("The backup cache file %s is corrupted.  Unlinking."), $backup));
757 cd25a2b2 jim-p
				unlink($backup);
758 4e038d31 Carlos Eduardo Ramos
				log_error(sprintf(gettext("The backup cache file %s is corrupted.  Unlinking."), $backup));
759 cd25a2b2 jim-p
				continue;
760 12df7edc Erik
			}
761 cd25a2b2 jim-p
			if($newxml['revision']['description'] == "")
762
				$newxml['revision']['description'] = "Unknown";
763 92420c0a jim-p
			if($newxml['version'] == "")
764
				$newxml['version'] = "?";
765
			$tocache[$tocheck] = array('description' => $newxml['revision']['description'], 'version' => $newxml['version']);
766 12df7edc Erik
		}
767 cd25a2b2 jim-p
	}
768
	foreach($backups as $checkbak) {
769
		if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
770
			$newbaks[] = $checkbak;
771
		} else {
772
			$i = true;
773
			if($g['booting']) print " " . $tocheck . "r";
774
		}
775
	}
776 92420c0a jim-p
	foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description'], 'version' => $todo['version']);
777 cd25a2b2 jim-p
	if(is_int($revisions) and (count($tocache) > $revisions)) {
778
		$toslice = array_slice(array_keys($tocache), 0, $revisions);
779
		foreach($toslice as $sliced)
780
			$newcache[$sliced] = $tocache[$sliced];
781
		foreach($tocache as $version => $versioninfo) {
782
			if(!in_array($version, array_keys($newcache))) {
783
				unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
784 1c42331b Scott Ullrich
				//if($g['booting']) print " " . $tocheck . "d";
785 12df7edc Erik
			}
786
		}
787 cd25a2b2 jim-p
		$tocache = $newcache;
788 12df7edc Erik
	}
789 cd25a2b2 jim-p
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
790
	fwrite($bakout, serialize($tocache));
791
	fclose($bakout);
792
	conf_mount_ro();
793
794 12df7edc Erik
	if (!$lock)
795
		unlock($lockkey);
796
}
797
798
function get_backups() {
799
	global $g;
800
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
801
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
802
		$bakvers = array_keys($confvers);
803
		$toreturn = array();
804
		sort($bakvers);
805
		// 	$bakvers = array_reverse($bakvers);
806
		foreach(array_reverse($bakvers) as $bakver)
807 92420c0a jim-p
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description'], 'version' => $confvers[$bakver]['version']);
808 12df7edc Erik
	} else {
809
		return false;
810
	}
811
	$toreturn['versions'] = $bakvers;
812
	return $toreturn;
813
}
814
815
function backup_config() {
816
	global $config, $g;
817
818
	if($g['platform'] == "cdrom")
819
		return;
820
821
	conf_mount_rw();
822
823
	/* Create backup directory if needed */
824
	safe_mkdir("{$g['cf_conf_path']}/backup");
825
826
    if($config['revision']['time'] == "") {
827
            $baktime = 0;
828
    } else {
829
            $baktime = $config['revision']['time'];
830
    }
831
    if($config['revision']['description'] == "") {
832
            $bakdesc = "Unknown";
833
    } else {
834
            $bakdesc = $config['revision']['description'];
835
    }
836 8059f9cb jim-p
837
	$bakver = ($config['version'] == "") ? "?" : $config['version'];
838
839 12df7edc Erik
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
840
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
841
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
842
    } else {
843
            $backupcache = array();
844
    }
845 8059f9cb jim-p
    $backupcache[$baktime] = array('description' => $bakdesc, 'version' => $bakver);
846 12df7edc Erik
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
847
    fwrite($bakout, serialize($backupcache));
848
    fclose($bakout);
849
850
	conf_mount_ro();
851
852
	return true;
853
}
854
855
function set_device_perms() {
856
	$devices = array(
857 573c9548 Ermal
		'pf'	=> array(	'user'	=> 'root',
858 12df7edc Erik
					'group'	=> 'proxy',
859
					'mode'	=> 0660),
860
		);
861
862
	foreach ($devices as $name => $attr) {
863
		$path = "/dev/$name";
864
		if (file_exists($path)) {
865
			chown($path, $attr['user']);
866
			chgrp($path, $attr['group']);
867
			chmod($path, $attr['mode']);
868
		}
869
	}
870
}
871
872 4e038d31 Carlos Eduardo Ramos
?>