Project

General

Profile

Download (25 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
	if(file_exists($g['conf_path'] . "/config.xml")) {
57
		if($g['booting']) {
58
			$configtxt = file_get_contents($g['conf_path'] . "/config.xml");			
59
			if(tagfile_deformat($configtxt, $configtxt, "config.xml")) {
60
				$fp = fopen('php://stdin', 'r');
61
				$data = "";
62
				echo "\n\n*** Encrypted config.xml detected ***\n";
63
				while($data == "") {
64
					echo "\nEnter the password to decrypt config.xml: ";
65
					$decrypt_password = chop(fgets($fp));
66
					$data = decrypt_data($configtxt, $decrypt_password);
67
					if(!strstr($data, "<pfsense>"))
68
						$data = "";
69
					if($data) {
70
						$fd = fopen($g['conf_path'] . "/config.xml.tmp", "w");
71
						fwrite($fd, $data);
72
						fclose($fd);
73
						exec("/bin/mv {$g['conf_path']}/config.xml.tmp {$g['conf_path']}/config.xml");
74
						echo "\nConfig.xml unlocked.\n";
75
						fclose($fp);
76
					} else {
77
						echo "\nInvalid password entered.  Please try again.\n";
78
					}
79
				}
80
			}
81
		}
82
	}
83
}
84

    
85
/****f* config/parse_config
86
 * NAME
87
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
88
 * INPUTS
89
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
90
 * RESULT
91
 *   $config      - array containing all configuration variables
92
 ******/
93
function parse_config($parse = false) {
94
	global $g, $config_parsed, $config_extra;
95
	
96
	$lockkey = lock('config');
97
	$config_parsed = false;
98
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
99
		$last_backup = discover_last_backup();
100
		if($last_backup) {
101
			log_error("No config.xml found, attempting last known config restore.");
102
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
103
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
104
		} else {
105
			unlock($lockkey);
106
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
107
		}
108
	}
109
	if($g['booting']) echo ".";
110
	// Check for encrypted config.xml
111
	encrypted_configxml();
112
	if(!$parse) {
113
		if(file_exists($g['tmp_path'] . '/config.cache')) {
114
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
115
			if(is_null($config)) {
116
				unlock($lockkey);
117
				parse_config(true);
118
				$lockkey = lock('config');
119
			}
120
		} else {
121
			if(!file_exists($g['conf_path'] . "/config.xml")) {
122
				log_error("No config.xml found, attempting last known config restore.");
123
				file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
124
				$last_backup = discover_last_backup();
125
				if ($last_backup)
126
					restore_backup("/cf/conf/backup/{$last_backup}");
127
				else {
128
					log_error("Could not restore config.xml.");
129
					unlock($lockkey);
130
					die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
131
				}
132
			}
133
			unlock($lockkey);
134
			$config = parse_config(true);
135
			$lockkey = lock('config');
136
		}
137
	} else {
138
		if(!file_exists($g['conf_path'] . "/config.xml")) {
139
			if($g['booting']) echo ".";
140
			log_error("No config.xml found, attempting last known config restore.");
141
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
142
			$last_backup = discover_last_backup();
143
			if ($last_backup)
144
				restore_backup("/cf/conf/backup/{$last_backup}");
145
			else {
146
				log_error("Could not restore config.xml.");
147
				unlock($lockkey);
148
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
149
			}
150
		}
151
		$config = parse_xml_config($g['conf_path'] . '/config.xml', array($g['xml_rootobj'], 'pfsense'));
152
		if($config == "-1") {
153
			$last_backup = discover_last_backup();
154
			if ($last_backup)
155
				restore_backup("/cf/conf/backup/{$last_backup}");
156
			else {
157
				log_error(gettext("Could not restore config.xml."));
158
				unlock($lockkey);
159
				die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
160
			}
161
		}
162
		generate_config_cache($config);
163
	}
164
	if($g['booting']) echo ".";
165
	alias_make_table($config);
166
	$config_parsed = true;
167
	unlock($lockkey);
168

    
169
	return $config;
170
}
171

    
172
/****f* config/generate_config_cache
173
 * NAME
174
 *   generate_config_cache - Write serialized configuration to cache.
175
 * INPUTS
176
 *   $config	- array containing current firewall configuration
177
 * RESULT
178
 *   boolean	- true on completion
179
 ******/
180
function generate_config_cache($config) {
181
	global $g, $config_extra;
182

    
183
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
184
	fwrite($configcache, serialize($config));
185
	fclose($configcache);
186
	unset($configcache);
187
	/* Used for config.extra.xml */
188
	if(file_exists($g['tmp_path'] . '/config.extra.cache') && $config_extra) {
189
		$configcacheextra = fopen($g['tmp_path'] . '/config.extra.cache', "w");
190
		fwrite($configcacheextra, serialize($config_extra));
191
		fclose($configcacheextra);		
192
		unset($configcacheextra);
193
	}
194
}
195

    
196
function discover_last_backup() {
197
        $backups = split("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
198
	$last_backup = "";
199
        foreach($backups as $backup)
200
        	if($backup)
201
	        	$last_backup = $backup;
202

    
203
        return $last_backup;
204
}
205

    
206
function restore_backup($file) {
207
	global $g;
208

    
209
	if (file_exists($file)) {
210
		conf_mount_rw();
211
		unlink_if_exists("{$g['tmp_path']}/config.cache");
212
		copy("$file","/cf/conf/config.xml");
213
		disable_security_checks();
214
		log_error("{$g['product_name']} is restoring the configuration $file");
215
		file_notice("config.xml", "{$g['product_name']} is restoring the configuration $file", "{$g['product_name']}Configurator", "");
216
		conf_mount_ro();
217
	}
218
}
219

    
220
/****f* config/parse_config_bootup
221
 * NAME
222
 *   parse_config_bootup - Bootup-specific configuration checks.
223
 * RESULT
224
 *   null
225
 ******/
226
function parse_config_bootup() {
227
	global $config, $g;
228

    
229
	if($g['booting']) echo ".";
230

    
231
	$lockkey = lock('config');
232
	if (!file_exists("{$g['conf_path']}/config.xml")) {
233
		if ($g['booting']) {
234
			if (strstr($g['platform'], "cdrom")) {
235
				/* try copying the default config. to the floppy */
236
				echo "Resetting factory defaults...\n";
237
				reset_factory_defaults(true);
238
				if (!file_exists("{$g['conf_path']}/config.xml")) {
239
					echo "No XML configuration file found - using factory defaults.\n";
240
					echo "Make sure that the configuration floppy disk with the conf/config.xml\n";
241
					echo "file is inserted. If it isn't, your configuration changes will be lost\n";
242
					echo "on reboot.\n";
243
				}
244
			} else {
245
				$last_backup = discover_last_backup();
246
				if($last_backup) {
247
					log_error("No config.xml found, attempting last known config restore.");
248
					file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
249
					restore_backup("/cf/conf/backup/{$last_backup}");
250
				}
251
				if(!file_exists("{$g['conf_path']}/config.xml")) {
252
					echo "XML configuration file not found.  {$g['product_name']} cannot continue booting.\n";
253
					mwexec("/sbin/halt");
254
					exit;
255
				}
256
				log_error("Last known config found and restored.  Please double check your configuration file for accuracy.");
257
				file_notice("config.xml", "Last known config found and restored.  Please double check your configuration file for accuracy.", "pfSenseConfigurator", "");
258
			}
259
		} else {
260
			unlock($lockkey);
261
			exit(0);
262
		}
263
	}
264

    
265
	if (filesize("{$g['conf_path']}/config.xml") == 0) {
266
		$last_backup = discover_last_backup();
267
		if($last_backup) {
268
			log_error("No config.xml found, attempting last known config restore.");
269
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
270
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
271
		} else {
272
			unlock($lockkey);
273
			die("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup.");
274
		}
275
	}
276
	unlock($lockkey);
277
	parse_config(true);
278

    
279
	if ((float)$config['version'] > (float)$g['latest_config']) {
280
		echo <<<EOD
281

    
282

    
283
*******************************************************************************
284
* WARNING!                                                                    *
285
* The current configuration has been created with a newer version of {$g['product_name']}  *
286
* than this one! This can lead to serious misbehavior and even security       *
287
* holes! You are urged to either upgrade to a newer version of {$g['product_name']} or     *
288
* revert to the default configuration immediately!                            *
289
*******************************************************************************
290

    
291

    
292
EOD;
293
		}
294

    
295
	/* make alias table (for faster lookups) */
296
	alias_make_table($config);
297
}
298

    
299
/****f* config/conf_mount_rw
300
 * NAME
301
 *   conf_mount_rw - Mount filesystems read/write.
302
 * RESULT
303
 *   null
304
 ******/
305
/* mount flash card read/write */
306
function conf_mount_rw() {
307
	global $g;
308

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

    
313
	if (refcount_reference(1000) > 1)
314
		return;
315

    
316
	$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
317
	if($status <> 0) {
318
		if($g['booting'])
319
			echo "Disk is dirty.  Running fsck -y\n";
320
		mwexec("/sbin/fsck -y {$g['cf_path']}");
321
		$status = mwexec("/sbin/mount -u -w {$g['cf_path']}");
322
	}
323

    
324
	/*    if the platform is soekris or wrap or pfSense, lets mount the
325
	 *    compact flash cards root.
326
         */
327
	$status = mwexec("/sbin/mount -u -w /");
328
	/* we could not mount this correctly.  kick off fsck */
329
	if($status <> 0) {
330
		log_error("File system is dirty.  Launching FSCK for /");
331
		mwexec("/sbin/fsck -y /");
332
		$status = mwexec("/sbin/mount -u -w /");
333
	}
334
	
335
	mark_subsystem_dirty('mount');
336
}
337

    
338
/****f* config/conf_mount_ro
339
 * NAME
340
 *   conf_mount_ro - Mount filesystems readonly.
341
 * RESULT
342
 *   null
343
 ******/
344
function conf_mount_ro() {
345
	global $g;
346

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

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

    
354
	clear_subsystem_dirty('mount');
355
	/* sync data, then force a remount of /cf */
356
	pfSense_sync();
357
	mwexec("/sbin/mount -u -r -f {$g['cf_path']}");
358
	mwexec("/sbin/mount -u -r -f /");
359
}
360

    
361
/****f* config/convert_config
362
 * NAME
363
 *   convert_config - Attempt to update config.xml.
364
 * DESCRIPTION
365
 *   convert_config() reads the current global configuration
366
 *   and attempts to convert it to conform to the latest
367
 *   config.xml version. This allows major formatting changes
368
 *   to be made with a minimum of breakage.
369
 * RESULT
370
 *   null
371
 ******/
372
/* convert configuration, if necessary */
373
function convert_config() {
374
	global $config, $g;
375
	$now = date("H:i:s");
376
	log_error("Start Configuration upgrade at $now, set execution timeout to 15 minutes");
377
	//ini_set("max_execution_time", "900");
378

    
379
	/* special case upgrades */
380
	/* fix every minute crontab bogons entry */
381
	$cron_item_count = count($config['cron']['item']);
382
	for($x=0; $x<$cron_item_count; $x++) {
383
		if(stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
384
			if($config['cron']['item'][$x]['hour'] == "*" ) {
385
		        $config['cron']['item'][$x]['hour'] = "3";
386
		 		write_config("Updated bogon update frequency to 3am");
387
		 		log_error("Updated bogon update frequency to 3am");
388
		 	}       
389
		}
390
	}
391
	if ($config['version'] == $g['latest_config'])
392
		return;		/* already at latest version */
393

    
394
	// Save off config version
395
	$prev_version = $config['version'];
396
	
397
	include_once('auth.inc');
398
	include_once('upgrade_config.inc');
399
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
400
	while ($config['version'] < $g['latest_config']) {
401
		$cur = $config['version'] * 10;
402
		$next = $cur + 1;
403
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
404
		$migration_function();
405
		$config['version'] = sprintf('%.1f', $next / 10);
406
		if($g['booting'])
407
			echo ".";
408
	}
409

    
410
	$now = date("H:i:s");
411
	log_error("Ended Configuration upgrade at $now");
412

    
413
	if ($prev_version != $config['version'])
414
		write_config("Upgraded config version level from {$prev_version} to {$config['version']}");
415
}
416

    
417
/****f* config/safe_write_file
418
 * NAME
419
 *   safe_write_file - Write a file out atomically
420
 * DESCRIPTION
421
 *   safe_write_file() Writes a file out atomically by first writing to a
422
 *   temporary file of the same name but ending with the pid of the current
423
 *   process, them renaming the temporary file over the original.
424
 * INPUTS
425
 *   $filename  - string containing the filename of the file to write
426
 *   $content   - string containing the file content to write to file
427
 *   $force_binary      - boolean denoting whether we should force binary
428
 *   mode writing.
429
 * RESULT
430
 *   boolean - true if successful, false if not
431
 ******/
432
function safe_write_file($file, $content, $force_binary) {
433
	$tmp_file = $file . "." . getmypid();
434
	$write_mode = $force_binary ? "wb" : "w";
435

    
436
	$fd = fopen($tmp_file, $write_mode);
437
	if (!$fd) {
438
		// Unable to open temporary file for writing
439
		return false;
440
        }
441
	if (!fwrite($fd, $content)) {
442
		// Unable to write to temporary file
443
		fclose($fd);
444
		return false;
445
	}
446
	fflush($fd);
447
	fclose($fd);
448

    
449
	if (!rename($tmp_file, $file)) {
450
		// Unable to move temporary file to original
451
		@unlink($tmp_file);
452
		return false;
453
	}
454

    
455
	// Sync file before returning
456
	pfSense_sync();
457

    
458
	return true;
459
}
460

    
461
/****f* config/write_config
462
 * NAME
463
 *   write_config - Backup and write the firewall configuration.
464
 * DESCRIPTION
465
 *   write_config() handles backing up the current configuration,
466
 *   applying changes, and regenerating the configuration cache.
467
 * INPUTS
468
 *   $desc	- string containing the a description of configuration changes
469
 *   $backup	- boolean: do not back up current configuration if false.
470
 * RESULT
471
 *   null
472
 ******/
473
/* save the system configuration */
474
function write_config($desc="Unknown", $backup = true) {
475
	global $config, $g;
476

    
477
	/* TODO: Not sure what this was added for; commenting out
478
	 *       for now, since it was preventing config saving. */
479
	// $config = parse_config(true, false, false);
480
	
481
	if($g['bootup']) 
482
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
483

    
484
	if($backup)
485
		backup_config();
486

    
487
	if (!is_array($config['revision']))
488
		$config['revision'] = array();
489

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

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

    
497
	$config['revision']['description'] = "{$_SESSION['Username']}: " . $desc;
498
	$config['revision']['username'] = $_SESSION["Username"];
499

    
500
	conf_mount_rw();
501
	$lockkey = lock('config', LOCK_EX);
502

    
503
	/* generate configuration XML */
504
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
505

    
506
	/* write new configuration */
507
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
508
		log_error("WARNING: Config contents could not be save. Could not open file!");
509
		unlock($lockkey);
510
		file_notice("config.xml", "Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
511
		return -1;
512
	}
513
	
514
	if($g['platform'] == "embedded" or $g['platform'] == "nanobsd") {
515
		cleanup_backupcache(5, true);
516
	} else {
517
		cleanup_backupcache(30, true);
518
	}
519

    
520
	/* re-read configuration */
521
	/* NOTE: We assume that the file can be parsed since we wrote it. */
522
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
523
	if ($config == -1) {
524
		$last_backup = discover_last_backup();
525
		if ($last_backup)
526
			restore_backup("/cf/conf/backup/{$last_backup}");
527
		else
528
			log_error(gettext("Could not restore config.xml."));
529
	} else
530
		generate_config_cache($config);
531

    
532
	unlock($lockkey);
533

    
534
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
535

    
536
	/* tell kernel to sync fs data */
537
	conf_mount_ro();
538

    
539
	/* sync carp entries to other firewalls */
540
	carp_sync_client();
541

    
542
	if(is_dir("/usr/local/pkg/write_config")) {
543
		/* process packager manager custom rules */
544
		run_plugins("/usr/local/pkg/write_config/");
545
	}
546

    
547
	return $config;
548
}
549

    
550
/****f* config/reset_factory_defaults
551
 * NAME
552
 *   reset_factory_defaults - Reset the system to its default configuration.
553
 * RESULT
554
 *   integer	- indicates completion
555
 ******/
556
function reset_factory_defaults($lock = false) {
557
	global $g;
558

    
559
	conf_mount_rw();
560
	if (!$lock)
561
		$lockkey = lock('config', LOCK_EX);
562

    
563
	/* create conf directory, if necessary */
564
	safe_mkdir("{$g['cf_conf_path']}");
565

    
566
	/* clear out /conf */
567
	$dh = opendir($g['conf_path']);
568
	while ($filename = readdir($dh)) {
569
		if (($filename != ".") && ($filename != "..")) {
570
			unlink_if_exists($g['conf_path'] . "/" . $filename);
571
		}
572
	}
573
	closedir($dh);
574

    
575
	/* copy default configuration */
576
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
577

    
578
	disable_security_checks();
579

    
580
	/* call the wizard */
581
	touch("/conf/trigger_initial_wizard");
582
	if (!$lock)
583
		unlock($lockkey);
584
	conf_mount_ro();
585

    
586
	return 0;
587
}
588

    
589
function config_restore($conffile) {
590
	global $config, $g;
591

    
592
	if (!file_exists($conffile))
593
		return 1;
594

    
595
	backup_config();
596

    
597
	conf_mount_rw();
598
	
599
	$lockkey = lock('config', LOCK_EX);
600

    
601
	unlink_if_exists("{$g['tmp_path']}/config.cache");
602
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
603

    
604
	disable_security_checks();
605

    
606
	unlock($lockkey);
607

    
608
	$config = parse_config(true);
609

    
610
	conf_mount_ro();
611

    
612
	write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
613

    
614
	return 0;
615
}
616

    
617
function config_install($conffile) {
618
	global $config, $g;
619

    
620
	if (!file_exists($conffile))
621
		return 1;
622

    
623
	if (!config_validate("{$conffile}"))
624
		return 1;
625

    
626
	if($g['booting'] == true)
627
		echo "Installing configuration...\n";
628
	else
629
		log_error("Installing configuration ....");
630

    
631
	conf_mount_rw();
632
	$lockkey = lock('config', LOCK_EX);
633

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

    
636
	disable_security_checks();
637

    
638
	/* unlink cache file if it exists */
639
	if(file_exists("{$g['tmp_path']}/config.cache"))
640
		unlink("{$g['tmp_path']}/config.cache");
641

    
642
	unlock($lockkey);
643
	conf_mount_ro();
644

    
645
    return 0;
646
}
647

    
648
/*
649
 * Disable security checks for DNS rebind and HTTP referrer until next time
650
 * they pass (or reboot), to aid in preventing accidental lockout when
651
 * restoring settings like hostname, domain, IP addresses, and settings
652
 * related to the DNS rebind and HTTP referrer checks.
653
 * Intended for use when restoring a configuration or directly
654
 * modifying config.xml without an unconditional reboot.
655
 */
656
function disable_security_checks() {
657
	global $g;
658
	touch("{$g['tmp_path']}/disable_security_checks");
659
}
660

    
661
/* Restores security checks.  Should be called after all succeed. */
662
function restore_security_checks() {
663
	global $g;
664
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
665
}
666

    
667
/* Returns status of security check temporary disable. */
668
function security_checks_disabled() {
669
	global $g;
670
	return file_exists("{$g['tmp_path']}/disable_security_checks");
671
}
672

    
673
function config_validate($conffile) {
674

    
675
	global $g, $xmlerr;
676

    
677
	$xml_parser = xml_parser_create();
678

    
679
	if (!($fp = fopen($conffile, "r"))) {
680
		$xmlerr = "XML error: unable to open file";
681
		return false;
682
	}
683

    
684
	while ($data = fread($fp, 4096)) {
685
		if (!xml_parse($xml_parser, $data, feof($fp))) {
686
			$xmlerr = sprintf("%s at line %d",
687
						xml_error_string(xml_get_error_code($xml_parser)),
688
						xml_get_current_line_number($xml_parser));
689
			return false;
690
		}
691
	}
692
	xml_parser_free($xml_parser);
693

    
694
	fclose($fp);
695

    
696
	return true;
697
}
698

    
699
function cleanup_backupcache($revisions = 30, $lock = false) {
700
	global $g;
701
	$i = false;
702
	
703
	if (!$lock)
704
		$lockkey = lock('config');
705

    
706
	conf_mount_rw();
707

    
708
	$backups = get_backups();
709
	if ($backups) {
710
		$baktimes = $backups['versions'];
711
		unset($backups['versions']);
712
	} else {
713
		$backups = array();
714
		$baktimes = array();
715
	}
716
	$newbaks = array();
717
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
718
	$tocache = array();
719

    
720
	foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
721
		if(filesize($backup) == 0) {
722
			unlink($backup);
723
			continue;
724
		}
725
		$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
726
		if(!in_array($tocheck, $baktimes)) {
727
			$i = true;
728
			if($g['booting'])
729
				echo ".";
730
			$newxml = parse_xml_config($backup, array($g['xml_rootobj'], 'pfsense'));
731
			if($newxml == "-1") {
732
				log_error("The backup cache file $backup is corrupted.  Unlinking.");
733
				unlink($backup);
734
				log_error("The backup cache file $backup is corrupted.  Unlinking.");
735
				continue;
736
			}
737
			if($newxml['revision']['description'] == "")
738
				$newxml['revision']['description'] = "Unknown";
739
			$tocache[$tocheck] = array('description' => $newxml['revision']['description']);
740
		}
741
	}
742
	foreach($backups as $checkbak) {
743
		if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
744
			$newbaks[] = $checkbak;
745
		} else {
746
			$i = true;
747
			if($g['booting']) print " " . $tocheck . "r";
748
		}
749
	}
750
	foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description']);
751
	if(is_int($revisions) and (count($tocache) > $revisions)) {
752
		$toslice = array_slice(array_keys($tocache), 0, $revisions);
753
		foreach($toslice as $sliced)
754
			$newcache[$sliced] = $tocache[$sliced];
755
		foreach($tocache as $version => $versioninfo) {
756
			if(!in_array($version, array_keys($newcache))) {
757
				unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
758
				if($g['booting']) print " " . $tocheck . "d";
759
			}
760
		}
761
		$tocache = $newcache;
762
	}
763
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
764
	fwrite($bakout, serialize($tocache));
765
	fclose($bakout);
766
	conf_mount_ro();
767

    
768
	if (!$lock)
769
		unlock($lockkey);
770
}
771

    
772
function get_backups() {
773
	global $g;
774
	if(file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
775
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
776
		$bakvers = array_keys($confvers);
777
		$toreturn = array();
778
		sort($bakvers);
779
		// 	$bakvers = array_reverse($bakvers);
780
		foreach(array_reverse($bakvers) as $bakver)
781
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description']);
782
	} else {
783
		return false;
784
	}
785
	$toreturn['versions'] = $bakvers;
786
	return $toreturn;
787
}
788

    
789
function backup_config() {
790
	global $config, $g;
791

    
792
	if($g['platform'] == "cdrom")
793
		return;
794

    
795
	conf_mount_rw();
796

    
797
	/* Create backup directory if needed */
798
	safe_mkdir("{$g['cf_conf_path']}/backup");
799

    
800
    if($config['revision']['time'] == "") {
801
            $baktime = 0;
802
    } else {
803
            $baktime = $config['revision']['time'];
804
    }
805
    if($config['revision']['description'] == "") {
806
            $bakdesc = "Unknown";
807
    } else {
808
            $bakdesc = $config['revision']['description'];
809
    }
810
    copy($g['cf_conf_path'] . '/config.xml', $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml');
811
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
812
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
813
    } else {
814
            $backupcache = array();
815
    }
816
    $backupcache[$baktime] = array('description' => $bakdesc);
817
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
818
    fwrite($bakout, serialize($backupcache));
819
    fclose($bakout);
820

    
821
	conf_mount_ro();
822

    
823
	return true;
824
}
825

    
826
function set_device_perms() {
827
	$devices = array(
828
		'pf'	=> array(	'user'	=> 'root',
829
					'group'	=> 'proxy',
830
					'mode'	=> 0660),
831
		);
832

    
833
	foreach ($devices as $name => $attr) {
834
		$path = "/dev/$name";
835
		if (file_exists($path)) {
836
			chown($path, $attr['user']);
837
			chgrp($path, $attr['group']);
838
			chmod($path, $attr['mode']);
839
		}
840
	}
841
}
842

    
843
?>
(12-12/54)