Project

General

Profile

Download (25.1 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	/bin/sync
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", "pfSenseConfigurator", "");
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
	mwexec("/bin/sync; /bin/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
	if($g['booting'])
417
		echo "Loading new configuration...";
418
}
419

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

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

    
451
        if (!rename($tmp_file, $file)) {
452
                // Unable to move temporary file to original
453
                unlink($tmp_file);
454
                return false;
455
        }
456
        return true;
457
}
458

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

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

    
482
	if($backup)
483
		backup_config();
484

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

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

    
492
	$config['revision']['description'] = "{$_SESSION['Username']}: " . $desc;
493
	$config['revision']['username'] = $_SESSION["Username"];
494

    
495
	conf_mount_rw();
496
	$lockkey = lock('config', LOCK_EX);
497

    
498
	/* generate configuration XML */
499
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
500

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

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

    
527
	unlock($lockkey);
528

    
529
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
530

    
531
	/* tell kernel to sync fs data */
532
	conf_mount_ro();
533

    
534
	/* sync carp entries to other firewalls */
535
	carp_sync_client();
536

    
537
	if(is_dir("/usr/local/pkg/write_config")) {
538
		/* process packager manager custom rules */
539
		run_plugins("/usr/local/pkg/write_config/");
540
	}
541

    
542
	return $config;
543
}
544

    
545
/****f* config/reset_factory_defaults
546
 * NAME
547
 *   reset_factory_defaults - Reset the system to its default configuration.
548
 * RESULT
549
 *   integer	- indicates completion
550
 ******/
551
function reset_factory_defaults($lock = false) {
552
	global $g;
553

    
554
	conf_mount_rw();
555
	if (!$lock)
556
		$lockkey = lock('config', LOCK_EX);
557

    
558
	/* create conf directory, if necessary */
559
	safe_mkdir("{$g['cf_conf_path']}");
560

    
561
	/* clear out /conf */
562
	$dh = opendir($g['conf_path']);
563
	while ($filename = readdir($dh)) {
564
		if (($filename != ".") && ($filename != "..")) {
565
			unlink_if_exists($g['conf_path'] . "/" . $filename);
566
		}
567
	}
568
	closedir($dh);
569

    
570
	/* copy default configuration */
571
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
572

    
573
	disable_security_checks();
574

    
575
	/* call the wizard */
576
	touch("/conf/trigger_initial_wizard");
577
	if (!$lock)
578
		unlock($lockkey);
579
	conf_mount_ro();
580

    
581
	return 0;
582
}
583

    
584
function config_restore($conffile) {
585
	global $config, $g;
586

    
587
	if (!file_exists($conffile))
588
		return 1;
589

    
590
	backup_config();
591

    
592
	conf_mount_rw();
593
	
594
	$lockkey = lock('config', LOCK_EX);
595

    
596
	unlink_if_exists("{$g['tmp_path']}/config.cache");
597
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
598

    
599
	disable_security_checks();
600

    
601
	unlock($lockkey);
602

    
603
	$config = parse_config(true);
604

    
605
	conf_mount_ro();
606

    
607
	write_config("Reverted to " . array_pop(explode("/", $conffile)) . ".", false);
608

    
609
	return 0;
610
}
611

    
612
function config_install($conffile) {
613
	global $config, $g;
614

    
615
	if (!file_exists($conffile))
616
		return 1;
617

    
618
	if (!config_validate("{$conffile}"))
619
		return 1;
620

    
621
	if($g['booting'] == true)
622
		echo "Installing configuration...\n";
623
	else
624
		log_error("Installing configuration ....");
625

    
626
	conf_mount_rw();
627
	$lockkey = lock('config', LOCK_EX);
628

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

    
631
	disable_security_checks();
632

    
633
	/* unlink cache file if it exists */
634
	if(file_exists("{$g['tmp_path']}/config.cache"))
635
		unlink("{$g['tmp_path']}/config.cache");
636

    
637
	unlock($lockkey);
638
	conf_mount_ro();
639

    
640
    return 0;
641
}
642

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

    
656
/* Restores security checks.  Should be called after all succeed. */
657
function restore_security_checks() {
658
	global $g;
659
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
660
}
661

    
662
/* Returns status of security check temporary disable. */
663
function security_checks_disabled() {
664
	global $g;
665
	return file_exists("{$g['tmp_path']}/disable_security_checks");
666
}
667

    
668
function config_validate($conffile) {
669

    
670
	global $g, $xmlerr;
671

    
672
	$xml_parser = xml_parser_create();
673

    
674
	if (!($fp = fopen($conffile, "r"))) {
675
		$xmlerr = "XML error: unable to open file";
676
		return false;
677
	}
678

    
679
	while ($data = fread($fp, 4096)) {
680
		if (!xml_parse($xml_parser, $data, feof($fp))) {
681
			$xmlerr = sprintf("%s at line %d",
682
						xml_error_string(xml_get_error_code($xml_parser)),
683
						xml_get_current_line_number($xml_parser));
684
			return false;
685
		}
686
	}
687
	xml_parser_free($xml_parser);
688

    
689
	fclose($fp);
690

    
691
	return true;
692
}
693

    
694
function cleanup_backupcache($revisions = 30, $lock = false) {
695
	global $g;
696
	$i = false;
697
	
698
	if (!$lock)
699
		$lockkey = lock('config');
700

    
701
	conf_mount_rw();
702

    
703
	$backups = get_backups();
704
	if ($backups) {
705
		$baktimes = $backups['versions'];
706
		unset($backups['versions']);
707
	} else {
708
		$backups = array();
709
		$baktimes = array();
710
	}
711
	$newbaks = array();
712
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
713
	$tocache = array();
714

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

    
763
	if (!$lock)
764
		unlock($lockkey);
765
}
766

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

    
784
function backup_config() {
785
	global $config, $g;
786

    
787
	if($g['platform'] == "cdrom")
788
		return;
789

    
790
	conf_mount_rw();
791

    
792
	/* Create backup directory if needed */
793
	safe_mkdir("{$g['cf_conf_path']}/backup");
794

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

    
816
	conf_mount_ro();
817

    
818
	return true;
819
}
820

    
821
function set_device_perms() {
822
	$devices = array(
823
		'pf'	=> array(	'user'	=> 'root',
824
					'group'	=> 'proxy',
825
					'mode'	=> 0660),
826
		);
827

    
828
	foreach ($devices as $name => $attr) {
829
		$path = "/dev/$name";
830
		if (file_exists($path)) {
831
			chown($path, $attr['user']);
832
			chgrp($path, $attr['group']);
833
			chmod($path, $attr['mode']);
834
		}
835
	}
836
}
837

    
838
?>
(12-12/54)