Project

General

Profile

Download (25.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/config
3
 * NAME
4
 *   config.lib.inc - Functions to manipulate config.xml
5
 * 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
	Copyright (C) 2004-2010 Scott Ullrich
14
	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
	pfSense_BUILDER_BINARIES:	/sbin/mount	/sbin/sysctl	/sbin/umount	/sbin/halt	/sbin/fsck
43
	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

    
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
				$data = "";
74
			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
			}
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
function parse_config($parse = false) {
97
	global $g, $config_parsed, $config_extra;
98

    
99
	$lockkey = lock('config');
100
	$config_parsed = false;
101

    
102
	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

    
114
	if($g['booting'])
115
		echo ".";
116

    
117
	// Check for encrypted config.xml
118
	encrypted_configxml();
119

    
120
	if(!$parse) {
121
		if (file_exists($g['tmp_path'] . '/config.cache')) {
122
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
123
			if (is_null($config))
124
				$parse = true;
125
		} else
126
			$parse = true;
127
	}
128
	if ($parse == true) {
129
		if(!file_exists($g['conf_path'] . "/config.xml")) {
130
			if($g['booting'])
131
				echo ".";
132
			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
			else {
138
				log_error("Could not restore config.xml.");
139
				unlock($lockkey);
140
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
141
			}
142
		}
143
		$config = parse_xml_config($g['conf_path'] . '/config.xml', array($g['xml_rootobj'], 'pfsense'));
144
		if($config == -1) {
145
			$last_backup = discover_last_backup();
146
			if ($last_backup)
147
				restore_backup("/cf/conf/backup/{$last_backup}");
148
			else {
149
				log_error(gettext("Could not restore config.xml."));
150
				unlock($lockkey);
151
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
152
			}
153
		}
154
		generate_config_cache($config);
155
	}
156

    
157
	if($g['booting'])
158
		echo ".";
159

    
160
	$config_parsed = true;
161
	unlock($lockkey);
162

    
163
	alias_make_table($config);
164

    
165
	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
	global $g, $config_extra;
178

    
179
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
180
	fwrite($configcache, serialize($config));
181
	fclose($configcache);
182
	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
}
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
		copy("$file","/cf/conf/config.xml");
209
		disable_security_checks();
210
		log_error("{$g['product_name']} is restoring the configuration $file");
211
		file_notice("config.xml", "{$g['product_name']} is restoring the configuration $file", "{$g['product_name']}Configurator", "");
212
		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
	global $config, $g;
224

    
225
	if($g['booting'])
226
		echo ".";
227

    
228
	$lockkey = lock('config');
229
	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
				}
241
			} else {
242
				$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
					unlock($lockkey);
251
					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
			}
257
		} else {
258
			unlock($lockkey);
259
			exit(0);
260
		}
261
	}
262

    
263
	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
function conf_mount_rw() {
305
	global $g;
306

    
307
	/* do not mount on cdrom platform */
308
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
309
		return;
310

    
311
	if (refcount_reference(1000) > 1)
312
		return;
313

    
314
	$status = mwexec("/sbin/mount -u -w -o sync,noatime {$g['cf_path']}");
315
	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
		$status = mwexec("/sbin/mount -u -w -o sync,noatime {$g['cf_path']}");
320
	}
321

    
322
	/*    if the platform is soekris or wrap or pfSense, lets mount the
323
	 *    compact flash cards root.
324
         */
325
	$status = mwexec("/sbin/mount -u -w -o sync,noatime /");
326
	/* 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
		$status = mwexec("/sbin/mount -u -w -o sync,noatime /");
331
	}
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
function conf_mount_ro() {
343
	global $g;
344

    
345
	/* do not umount on cdrom or pfSense platforms */
346
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
347
		return;
348

    
349
	if($g['booting'])
350
		return;
351

    
352
	if (refcount_unreference(1000) > 0)
353
		return;
354

    
355
	clear_subsystem_dirty('mount');
356
	/* sync data, then force a remount of /cf */
357
	pfSense_sync();
358
	mwexec("/sbin/mount -u -r -f -o sync,noatime {$g['cf_path']}");
359
	mwexec("/sbin/mount -u -r -f -o sync,noatime /");
360
}
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
	//ini_set("max_execution_time", "900");
379

    
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
	include_once('auth.inc');
399
	include_once('upgrade_config.inc');
400
	if (file_exists("/etc/inc/upgrade_config_custom.inc"))
401
		include_once("upgrade_config_custom.inc");
402
	/* 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
		if (function_exists($migration_function))
408
			$migration_function();
409
		$migration_function = "{$migration_function}_custom";
410
		if (function_exists($migration_function))
411
			$migration_function();
412
		$config['version'] = sprintf('%.1f', $next / 10);
413
		if($g['booting'])
414
			echo ".";
415
	}
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
/****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
	$tmp_file = $file . "." . getmypid();
441
	$write_mode = $force_binary ? "wb" : "w";
442

    
443
	$fd = fopen($tmp_file, $write_mode);
444
	if (!$fd) {
445
		// Unable to open temporary file for writing
446
		return false;
447
        }
448
	if (!fwrite($fd, $content)) {
449
		// Unable to write to temporary file
450
		fclose($fd);
451
		return false;
452
	}
453
	fflush($fd);
454
	fclose($fd);
455

    
456
	if (!rename($tmp_file, $file)) {
457
		// Unable to move temporary file to original
458
		@unlink($tmp_file);
459
		return false;
460
	}
461

    
462
	// Sync file before returning
463
	pfSense_sync();
464

    
465
	return true;
466
}
467

    
468
/****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
	/* 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
	
488
	/* 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
	if($g['booting'])
492
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
493
	*/
494

    
495
	$username = empty($_SESSION["Username"]) ? "(system)" : $_SESSION['Username'];
496

    
497
	if($backup)
498
		backup_config();
499

    
500
	if (!is_array($config['revision']))
501
		$config['revision'] = array();
502

    
503
	if (time() > mktime(0, 0, 0, 9, 1, 2004))       /* make sure the clock settings are plausible */
504
		$config['revision']['time'] = time();
505

    
506
	/* Log the running script so it's not entirely unlogged what changed */
507
	if ($desc == "Unknown")
508
		$desc = "{$_SERVER['SCRIPT_NAME']} made unknown change";
509

    
510
	$config['revision']['description'] = "{$username}: " . $desc;
511
	$config['revision']['username'] = $username;
512

    
513
	conf_mount_rw();
514
	$lockkey = lock('config', LOCK_EX);
515

    
516
	/* generate configuration XML */
517
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
518

    
519
	/* write new configuration */
520
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
521
		log_error("WARNING: Config contents could not be save. Could not open file!");
522
		unlock($lockkey);
523
		file_notice("config.xml", "Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
524
		return -1;
525
	}
526
	
527
	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
	/* NOTE: We assume that the file can be parsed since we wrote it. */
535
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
536
	if ($config == -1) {
537
		copy("{$g['conf_path']}/config.xml", "{$g['conf_path']}/config.xml.bad");
538
		$last_backup = discover_last_backup();
539
		if ($last_backup) {
540
			restore_backup("/cf/conf/backup/{$last_backup}");
541
			$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
542
			if ($g['booting']) {
543
				echo "\n\n ************** WARNING **************";
544
				echo "\n\n Configuration could not be validated. A previous configuration was restored. \n";
545
				echo "\n The failed configuration file has been saved as {$g['conf_path']}/config.xml.bad} \n\n";
546
			}
547
		} else
548
			log_error(gettext("Could not restore config.xml."));
549
	} else
550
		generate_config_cache($config);
551

    
552
	unlock($lockkey);
553

    
554
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
555

    
556
	/* tell kernel to sync fs data */
557
	conf_mount_ro();
558

    
559
	/* sync carp entries to other firewalls */
560
	carp_sync_client();
561

    
562
	if(is_dir("/usr/local/pkg/write_config")) {
563
		/* process packager manager custom rules */
564
		run_plugins("/usr/local/pkg/write_config/");
565
	}
566

    
567
	return $config;
568
}
569

    
570
/****f* config/reset_factory_defaults
571
 * NAME
572
 *   reset_factory_defaults - Reset the system to its default configuration.
573
 * RESULT
574
 *   integer	- indicates completion
575
 ******/
576
function reset_factory_defaults($lock = false) {
577
	global $g;
578

    
579
	conf_mount_rw();
580
	if (!$lock)
581
		$lockkey = lock('config', LOCK_EX);
582

    
583
	/* create conf directory, if necessary */
584
	safe_mkdir("{$g['cf_conf_path']}");
585

    
586
	/* clear out /conf */
587
	$dh = opendir($g['conf_path']);
588
	while ($filename = readdir($dh)) {
589
		if (($filename != ".") && ($filename != "..")) {
590
			unlink_if_exists($g['conf_path'] . "/" . $filename);
591
		}
592
	}
593
	closedir($dh);
594

    
595
	/* copy default configuration */
596
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
597

    
598
	disable_security_checks();
599

    
600
	/* call the wizard */
601
	touch("/conf/trigger_initial_wizard");
602
	if (!$lock)
603
		unlock($lockkey);
604
	conf_mount_ro();
605

    
606
	return 0;
607
}
608

    
609
function config_restore($conffile) {
610
	global $config, $g;
611

    
612
	if (!file_exists($conffile))
613
		return 1;
614

    
615
	backup_config();
616

    
617
	conf_mount_rw();
618
	
619
	$lockkey = lock('config', LOCK_EX);
620

    
621
	unlink_if_exists("{$g['tmp_path']}/config.cache");
622
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
623

    
624
	disable_security_checks();
625

    
626
	unlock($lockkey);
627

    
628
	$config = parse_config(true);
629

    
630
	conf_mount_ro();
631

    
632
	write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
633

    
634
	return 0;
635
}
636

    
637
function config_install($conffile) {
638
	global $config, $g;
639

    
640
	if (!file_exists($conffile))
641
		return 1;
642

    
643
	if (!config_validate("{$conffile}"))
644
		return 1;
645

    
646
	if($g['booting'] == true)
647
		echo "Installing configuration...\n";
648
	else
649
		log_error("Installing configuration ....");
650

    
651
	conf_mount_rw();
652
	$lockkey = lock('config', LOCK_EX);
653

    
654
	copy($conffile, "{$g['conf_path']}/config.xml");
655

    
656
	disable_security_checks();
657

    
658
	/* unlink cache file if it exists */
659
	if(file_exists("{$g['tmp_path']}/config.cache"))
660
		unlink("{$g['tmp_path']}/config.cache");
661

    
662
	unlock($lockkey);
663
	conf_mount_ro();
664

    
665
    return 0;
666
}
667

    
668
/*
669
 * Disable security checks for DNS rebind and HTTP referrer until next time
670
 * they pass (or reboot), to aid in preventing accidental lockout when
671
 * restoring settings like hostname, domain, IP addresses, and settings
672
 * related to the DNS rebind and HTTP referrer checks.
673
 * Intended for use when restoring a configuration or directly
674
 * modifying config.xml without an unconditional reboot.
675
 */
676
function disable_security_checks() {
677
	global $g;
678
	touch("{$g['tmp_path']}/disable_security_checks");
679
}
680

    
681
/* Restores security checks.  Should be called after all succeed. */
682
function restore_security_checks() {
683
	global $g;
684
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
685
}
686

    
687
/* Returns status of security check temporary disable. */
688
function security_checks_disabled() {
689
	global $g;
690
	return file_exists("{$g['tmp_path']}/disable_security_checks");
691
}
692

    
693
function config_validate($conffile) {
694

    
695
	global $g, $xmlerr;
696

    
697
	$xml_parser = xml_parser_create();
698

    
699
	if (!($fp = fopen($conffile, "r"))) {
700
		$xmlerr = "XML error: unable to open file";
701
		return false;
702
	}
703

    
704
	while ($data = fread($fp, 4096)) {
705
		if (!xml_parse($xml_parser, $data, feof($fp))) {
706
			$xmlerr = sprintf("%s at line %d",
707
						xml_error_string(xml_get_error_code($xml_parser)),
708
						xml_get_current_line_number($xml_parser));
709
			return false;
710
		}
711
	}
712
	xml_parser_free($xml_parser);
713

    
714
	fclose($fp);
715

    
716
	return true;
717
}
718

    
719
function cleanup_backupcache($revisions = 30, $lock = false) {
720
	global $g;
721
	$i = false;
722
	
723
	if (!$lock)
724
		$lockkey = lock('config');
725

    
726
	conf_mount_rw();
727

    
728
	$backups = get_backups();
729
	if ($backups) {
730
		$baktimes = $backups['versions'];
731
		unset($backups['versions']);
732
	} else {
733
		$backups = array();
734
		$baktimes = array();
735
	}
736
	$newbaks = array();
737
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
738
	$tocache = array();
739

    
740
	foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
741
		if(filesize($backup) == 0) {
742
			unlink($backup);
743
			continue;
744
		}
745
		$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
746
		if(!in_array($tocheck, $baktimes)) {
747
			$i = true;
748
			if($g['booting'])
749
				echo ".";
750
			$newxml = parse_xml_config($backup, array($g['xml_rootobj'], 'pfsense'));
751
			if($newxml == "-1") {
752
				log_error("The backup cache file $backup is corrupted.  Unlinking.");
753
				unlink($backup);
754
				log_error("The backup cache file $backup is corrupted.  Unlinking.");
755
				continue;
756
			}
757
			if($newxml['revision']['description'] == "")
758
				$newxml['revision']['description'] = "Unknown";
759
			$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
760
		}
761
	}
762
	foreach($backups as $checkbak) {
763
		if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
764
			$newbaks[] = $checkbak;
765
		} else {
766
			$i = true;
767
			if($g['booting']) print " " . $tocheck . "r";
768
		}
769
	}
770
	foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);
771
	if(is_int($revisions) and (count($tocache) > $revisions)) {
772
		$toslice = array_slice(array_keys($tocache), 0, $revisions);
773
		foreach($toslice as $sliced)
774
			$newcache[$sliced] = $tocache[$sliced];
775
		foreach($tocache as $version => $versioninfo) {
776
			if(!in_array($version, array_keys($newcache))) {
777
				unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
778
				//if($g['booting']) print " " . $tocheck . "d";
779
			}
780
		}
781
		$tocache = $newcache;
782
	}
783
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
784
	fwrite($bakout, serialize($tocache));
785
	fclose($bakout);
786
	conf_mount_ro();
787

    
788
	if (!$lock)
789
		unlock($lockkey);
790
}
791

    
792
function get_backups() {
793
	global $g;
794
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
795
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
796
		$bakvers = array_keys($confvers);
797
		$toreturn = array();
798
		sort($bakvers);
799
		// 	$bakvers = array_reverse($bakvers);
800
		foreach(array_reverse($bakvers) as $bakver)
801
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
802
	} else {
803
		return false;
804
	}
805
	$toreturn['versions'] = $bakvers;
806
	return $toreturn;
807
}
808

    
809
function backup_config() {
810
	global $config, $g;
811

    
812
	if($g['platform'] == "cdrom")
813
		return;
814

    
815
	conf_mount_rw();
816

    
817
	/* Create backup directory if needed */
818
	safe_mkdir("{$g['cf_conf_path']}/backup");
819

    
820
    if($config['revision']['time'] == "") {
821
            $baktime = 0;
822
    } else {
823
            $baktime = $config['revision']['time'];
824
    }
825
    if($config['revision']['description'] == "") {
826
            $bakdesc = "Unknown";
827
    } else {
828
            $bakdesc = $config['revision']['description'];
829
    }
830
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
831
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
832
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
833
    } else {
834
            $backupcache = array();
835
    }
836
    $backupcache[$baktime] = array('description' => $bakdesc);
837
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
838
    fwrite($bakout, serialize($backupcache));
839
    fclose($bakout);
840

    
841
	conf_mount_ro();
842

    
843
	return true;
844
}
845

    
846
function set_device_perms() {
847
	$devices = array(
848
		'pf'	=> array(	'user'	=> 'root',
849
					'group'	=> 'proxy',
850
					'mode'	=> 0660),
851
		);
852

    
853
	foreach ($devices as $name => $attr) {
854
		$path = "/dev/$name";
855
		if (file_exists($path)) {
856
			chown($path, $attr['user']);
857
			chgrp($path, $attr['group']);
858
			chmod($path, $attr['mode']);
859
		}
860
	}
861
}
862

    
863
?>
(13-13/61)