Project

General

Profile

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