Project

General

Profile

Download (28 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * config.lib.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2009 Erik Kristensen
8
 * All rights reserved.
9
 *
10
 * originally part of m0n0wall (http://m0n0.ch/wall)
11
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
12
 * All rights reserved.
13
 *
14
 * Licensed under the Apache License, Version 2.0 (the "License");
15
 * you may not use this file except in compliance with the License.
16
 * You may obtain a copy of the License at
17
 *
18
 * http://www.apache.org/licenses/LICENSE-2.0
19
 *
20
 * Unless required by applicable law or agreed to in writing, software
21
 * distributed under the License is distributed on an "AS IS" BASIS,
22
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
 * See the License for the specific language governing permissions and
24
 * limitations under the License.
25
 */
26

    
27
/****f* config/encrypted_configxml
28
 * NAME
29
 *   encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock.
30
 * INPUTS
31
 *   None
32
 * RESULT
33
 *   $config 	- rewrites config.xml without encryption
34
 ******/
35
function encrypted_configxml() {
36
	global $g, $config;
37

    
38
	if (!file_exists($g['conf_path'] . "/config.xml")) {
39
		return;
40
	}
41

    
42
	if (!platform_booting()) {
43
		return;
44
	}
45

    
46
	$configtxt = file_get_contents($g['conf_path'] . "/config.xml");
47
	if (tagfile_deformat($configtxt, $configtxt, "config.xml")) {
48
		$fp = fopen('php://stdin', 'r');
49
		$data = "";
50
		echo "\n\n*** Encrypted config.xml detected ***\n";
51
		while ($data == "") {
52
			echo "\nEnter the password to decrypt config.xml: ";
53
			$decrypt_password = chop(fgets($fp));
54
			$data = decrypt_data($configtxt, $decrypt_password);
55
			if (!strstr($data, "<pfsense>")) {
56
				$data = "";
57
			}
58
			if ($data) {
59
				$fd = fopen($g['conf_path'] . "/config.xml.tmp", "w");
60
				fwrite($fd, $data);
61
				fclose($fd);
62
				exec("/bin/mv {$g['conf_path']}/config.xml.tmp {$g['conf_path']}/config.xml");
63
				echo "\n" . gettext("Config.xml unlocked.") . "\n";
64
				fclose($fp);
65
				pfSense_fsync("{$g['conf_path']}/config.xml");
66
			} else {
67
				echo "\n" . gettext("Invalid password entered.  Please try again.") . "\n";
68
			}
69
		}
70
	}
71
}
72

    
73
/****f* config/parse_config
74
 * NAME
75
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
76
 * INPUTS
77
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
78
 * RESULT
79
 *   $config      - array containing all configuration variables
80
 ******/
81
function parse_config($parse = false) {
82
	global $g, $config_parsed, $config_extra;
83

    
84
	$lockkey = lock('config');
85
	$config_parsed = false;
86

    
87
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
88
		$last_backup = discover_last_backup();
89
		if ($last_backup) {
90
			log_error(gettext("No config.xml found, attempting last known config restore."));
91
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
92
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
93
		} else {
94
			unlock($lockkey);
95
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
96
		}
97
	}
98

    
99
	if (platform_booting(true)) {
100
		echo ".";
101
	}
102

    
103
	// Check for encrypted config.xml
104
	encrypted_configxml();
105

    
106
	if (!$parse) {
107
		if (file_exists($g['tmp_path'] . '/config.cache')) {
108
			$config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache'));
109
			if (!is_array($config)) {
110
				$parse = true;
111
			}
112
		} else {
113
			$parse = true;
114
		}
115
	}
116
	if ($parse == true) {
117
		if (!file_exists($g['conf_path'] . "/config.xml")) {
118
			if (platform_booting(true)) {
119
				echo ".";
120
			}
121
			log_error("No config.xml found, attempting last known config restore.");
122
			file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", "");
123
			$last_backup = discover_last_backup();
124
			if ($last_backup) {
125
				restore_backup("/cf/conf/backup/{$last_backup}");
126
			} else {
127
				log_error(gettext("Could not restore config.xml."));
128
				unlock($lockkey);
129
				die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
130
			}
131
		}
132
		$config = parse_xml_config($g['conf_path'] . '/config.xml', array($g['xml_rootobj'], 'pfsense'));
133
		if ($config == -1) {
134
			$last_backup = discover_last_backup();
135
			if ($last_backup) {
136
				restore_backup("/cf/conf/backup/{$last_backup}");
137
			} else {
138
				log_error(gettext("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
		generate_config_cache($config);
144
	}
145

    
146
	if (platform_booting(true)) {
147
		echo ".";
148
	}
149

    
150
	$config_parsed = true;
151
	unlock($lockkey);
152

    
153
	alias_make_table($config);
154

    
155
	return $config;
156
}
157

    
158
/****f* config/generate_config_cache
159
 * NAME
160
 *   generate_config_cache - Write serialized configuration to cache.
161
 * INPUTS
162
 *   $config	- array containing current firewall configuration
163
 * RESULT
164
 *   boolean	- true on completion
165
 ******/
166
function generate_config_cache($config) {
167
	global $g, $config_extra;
168

    
169
	$configcache = fopen($g['tmp_path'] . '/config.cache', "w");
170
	fwrite($configcache, serialize($config));
171
	fclose($configcache);
172
	pfSense_fsync("{$g['tmp_path']}/config.cache");
173

    
174
	unset($configcache);
175
	/* Used for config.extra.xml */
176
	if (file_exists($g['tmp_path'] . '/config.extra.cache') && $config_extra) {
177
		$configcacheextra = fopen($g['tmp_path'] . '/config.extra.cache', "w");
178
		fwrite($configcacheextra, serialize($config_extra));
179
		fclose($configcacheextra);
180
		pfSense_fsync("{$g['tmp_path']}/config.extra.cache");
181
		unset($configcacheextra);
182
	}
183
}
184

    
185
function discover_last_backup() {
186
	$backups = glob('/cf/conf/backup/*.xml');
187
	$last_backup = "";
188
	$last_mtime = 0;
189
	foreach ($backups as $backup) {
190
		if (filemtime($backup) > $last_mtime) {
191
			$last_mtime = filemtime($backup);
192
			$last_backup = $backup;
193
		}
194
	}
195

    
196
	return basename($last_backup);
197
}
198

    
199
function restore_backup($file) {
200
	global $g;
201

    
202
	if (file_exists($file)) {
203
		unlink_if_exists("{$g['tmp_path']}/config.cache");
204
		copy("$file", "/cf/conf/config.xml");
205
		pfSense_fsync("/cf/conf/config.xml");
206
		pfSense_fsync($g['conf_path']);
207
		disable_security_checks();
208
		log_error(sprintf(gettext('%1$s is restoring the configuration %2$s'), $g['product_name'], $file));
209
		file_notice("config.xml", sprintf(gettext('%1$s is restoring the configuration %2$s'), $g['product_name'], $file), "pfSenseConfigurator", "");
210
	}
211
}
212

    
213
/****f* config/parse_config_bootup
214
 * NAME
215
 *   parse_config_bootup - Bootup-specific configuration checks.
216
 * RESULT
217
 *   null
218
 ******/
219
function parse_config_bootup() {
220
	global $config, $g;
221

    
222
	if (platform_booting()) {
223
		echo ".";
224
	}
225

    
226
	$lockkey = lock('config');
227
	if (!file_exists("{$g['conf_path']}/config.xml")) {
228
		if (platform_booting()) {
229
			$last_backup = discover_last_backup();
230
			if ($last_backup) {
231
				log_error("No config.xml found, attempting last known config restore.");
232
				file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
233
				restore_backup("/cf/conf/backup/{$last_backup}");
234
			}
235
			if (!file_exists("{$g['conf_path']}/config.xml")) {
236
				echo sprintf(gettext("XML configuration file not found.  %s cannot continue booting."), $g['product_name']) . "\n";
237
				unlock($lockkey);
238
				mwexec("/sbin/halt");
239
				exit;
240
			}
241
			log_error("Last known config found and restored.  Please double check the configuration file for accuracy.");
242
			file_notice("config.xml", gettext("Last known config found and restored.  Please double check the configuration file for accuracy."), "pfSenseConfigurator", "");
243
		} else {
244
			unlock($lockkey);
245
			log_error(gettext("Could not find a usable configuration file! Exiting...."));
246
			exit(0);
247
		}
248
	}
249

    
250
	if (filesize("{$g['conf_path']}/config.xml") == 0) {
251
		$last_backup = discover_last_backup();
252
		if ($last_backup) {
253
			log_error(gettext("No config.xml found, attempting last known config restore."));
254
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
255
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
256
		} else {
257
			unlock($lockkey);
258
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
259
		}
260
	}
261
	unlock($lockkey);
262

    
263
	$config = parse_config(true);
264

    
265
	if ((float)$config['version'] > (float)$g['latest_config']) {
266
		echo <<<EOD
267

    
268

    
269
*******************************************************************************
270
* WARNING!                                                                    *
271
* The current configuration has been created with a newer version of {$g['product_name']}  *
272
* than this one! This can lead to serious misbehavior and even security       *
273
* holes! You are urged to either upgrade to a newer version of {$g['product_name']} or     *
274
* revert to the default configuration immediately!                            *
275
*******************************************************************************
276

    
277

    
278
EOD;
279
		}
280

    
281
	/* make alias table (for faster lookups) */
282
	alias_make_table($config);
283
}
284

    
285
/****f* config/conf_mount_rw
286
 * NAME
287
 *   conf_mount_rw - Mount filesystems read/write.
288
 * RESULT
289
 *   null
290
 ******/
291
/* mount flash card read/write */
292
function conf_mount_rw() {
293
	/* Obsoleted. Keep it here untill all calls are removed */
294
	return;
295
}
296

    
297
/****f* config/conf_mount_ro
298
 * NAME
299
 *   conf_mount_ro - Mount filesystems readonly.
300
 * RESULT
301
 *   null
302
 ******/
303
function conf_mount_ro() {
304
	/* Obsoleted. Keep it here untill all calls are removed */
305
	return;
306
}
307

    
308
/****f* config/convert_config
309
 * NAME
310
 *   convert_config - Attempt to update config.xml.
311
 * DESCRIPTION
312
 *   convert_config() reads the current global configuration
313
 *   and attempts to convert it to conform to the latest
314
 *   config.xml version. This allows major formatting changes
315
 *   to be made with a minimum of breakage.
316
 * RESULT
317
 *   null
318
 ******/
319
/* convert configuration, if necessary */
320
function convert_config() {
321
	global $config, $g;
322
	$now = date("H:i:s");
323
	log_error(sprintf(gettext("Start Configuration upgrade at %s, set execution timeout to 15 minutes"), $now));
324
	//ini_set("max_execution_time", "900");
325

    
326
	/* special case upgrades */
327
	/* fix every minute crontab bogons entry */
328
	if (is_array($config['cron'])) {
329
		$cron_item_count = count($config['cron']['item']);
330
		for ($x = 0; $x < $cron_item_count; $x++) {
331
			if (stristr($config['cron']['item'][$x]['command'], "rc.update_bogons.sh")) {
332
				if ($config['cron']['item'][$x]['hour'] == "*") {
333
					$config['cron']['item'][$x]['hour'] = "3";
334
					write_config(gettext("Updated bogon update frequency to 3am"));
335
					log_error(gettext("Updated bogon update frequency to 3am"));
336
				}
337
			}
338
		}
339
	}
340
	if ($config['version'] == $g['latest_config']) {
341
		return;		/* already at latest version */
342
	}
343

    
344
	// Save off config version
345
	$prev_version = $config['version'];
346

    
347
	include_once('auth.inc');
348
	include_once('upgrade_config.inc');
349
	if (file_exists("/etc/inc/upgrade_config_custom.inc")) {
350
		include_once("upgrade_config_custom.inc");
351
	}
352

    
353
	if (!is_array($config['system']['already_run_config_upgrade'])) {
354
		$config['system']['already_run_config_upgrade'] = array();
355
	}
356
	$already_run =& $config['system']['already_run_config_upgrade'];
357

    
358
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
359
	while ($config['version'] < $g['latest_config']) {
360
		$cur = $config['version'] * 10;
361
		$next = $cur + 1;
362
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur,
363
		    $next);
364

    
365
		foreach (array("", "_custom") as $suffix) {
366
			$migration_function .= $suffix;
367
			if (!function_exists($migration_function)) {
368
				continue;
369
			}
370
			if (isset($already_run[$migration_function])) {
371
				/* Already executed, skip now */
372
				unset($already_run[$migration_function]);
373
			} else {
374
				$migration_function();
375
			}
376
		}
377
		$config['version'] = sprintf('%.1f', $next / 10);
378
		if (platform_booting()) {
379
			echo ".";
380
		}
381
	}
382

    
383
	additional_config_upgrade();
384

    
385
	$now = date("H:i:s");
386
	log_error(sprintf(gettext("Ended Configuration upgrade at %s"), $now));
387

    
388
	if ($prev_version != $config['version']) {
389
		write_config(sprintf(gettext('Upgraded config version level from %1$s to %2$s'), $prev_version, $config['version']));
390
	}
391
}
392

    
393
/****f* config/safe_write_file
394
 * NAME
395
 *   safe_write_file - Write a file out atomically
396
 * DESCRIPTION
397
 *   safe_write_file() Writes a file out atomically by first writing to a
398
 *   temporary file of the same name but ending with the pid of the current
399
 *   process, them renaming the temporary file over the original.
400
 * INPUTS
401
 *   $filename  - string containing the filename of the file to write
402
 *   $content   - string or array containing the file content to write to file
403
 *   $force_binary      - boolean denoting whether we should force binary
404
 *   mode writing.
405
 * RESULT
406
 *   boolean - true if successful, false if not
407
 ******/
408
function safe_write_file($file, $content, $force_binary = false) {
409
	$tmp_file = $file . "." . getmypid();
410
	$write_mode = $force_binary ? "wb" : "w";
411

    
412
	$fd = fopen($tmp_file, $write_mode);
413
	if (!$fd) {
414
		// Unable to open temporary file for writing
415
		return false;
416
	}
417
	if (is_array($content)) {
418
		foreach ($content as $line) {
419
			if (!fwrite($fd, $line . "\n")) {
420
				// Unable to write to temporary file
421
				fclose($fd);
422
				return false;
423
			}
424
		}
425
	} elseif (!fwrite($fd, $content)) {
426
		// Unable to write to temporary file
427
		fclose($fd);
428
		return false;
429
	}
430
	fflush($fd);
431
	fclose($fd);
432

    
433
	if (!pfSense_fsync($tmp_file) || !rename($tmp_file, $file)) {
434
		// Unable to move temporary file to original
435
		@unlink($tmp_file);
436
		return false;
437
	}
438

    
439
	// Sync file before returning
440
	return pfSense_fsync($file);
441
}
442

    
443
/****f* config/write_config
444
 * NAME
445
 *   write_config - Backup and write the firewall configuration.
446
 * DESCRIPTION
447
 *   write_config() handles backing up the current configuration,
448
 *   applying changes, and regenerating the configuration cache.
449
 * INPUTS
450
 *   $desc	- string containing the a description of configuration changes
451
 *   $backup	- boolean: do not back up current configuration if false.
452
 *   $write_config_only	- boolean: do not sync or reload anything; just save the configuration if true.
453
 * RESULT
454
 *   null
455
 ******/
456
/* save the system configuration */
457
function write_config($desc="Unknown", $backup = true, $write_config_only = false) {
458
	global $config, $g;
459

    
460
	if (!empty($_SERVER['REMOTE_ADDR'])) {
461
		@phpsession_begin();
462
		if (!empty($_SESSION['Username']) && ($_SESSION['Username'] != "admin")) {
463
			$user = getUserEntry($_SESSION['Username']);
464
			if (is_array($user) && userHasPrivilege($user, "user-config-readonly")) {
465
				syslog(LOG_AUTHPRIV, sprintf(gettext("Save config permission denied by the 'User - Config: Deny Config Write' permission for user '%s'."), $_SESSION['Username']));
466
				phpsession_end(true);
467
				return false;
468
			}
469
		}
470
		if (!isset($argc)) {
471
			phpsession_end(true);
472
		}
473
	}
474

    
475
	if (isset($config['reset_factory_defaults'])) {
476
		/*
477
		   We have put a default config.xml on disk and are about to reboot
478
		   or reload it. Do not let any system or package code try to save
479
		   state to config because that would overwrite the default config
480
		   with the running config.
481
		*/
482
		return false;
483
	}
484

    
485
	if ($backup) {
486
		backup_config();
487
	}
488

    
489
	$config['revision'] = make_config_revision_entry($desc);
490

    
491
	$lockkey = lock('config', LOCK_EX);
492

    
493
	/* generate configuration XML */
494
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
495

    
496
	/* write new configuration */
497
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig)) {
498
		log_error(gettext("WARNING: Config contents could not be saved. Could not open file!"));
499
		unlock($lockkey);
500
		file_notice("config.xml", sprintf(gettext('Unable to open %1$s/config.xml for writing in write_config()%2$s'), $g['cf_conf_path'], "\n"));
501
		return -1;
502
	}
503

    
504
	cleanup_backupcache(true);
505

    
506
	/* re-read configuration */
507
	/* NOTE: We assume that the file can be parsed since we wrote it. */
508
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
509
	if ($config == -1) {
510
		copy("{$g['conf_path']}/config.xml", "{$g['conf_path']}/config.xml.bad");
511
		$last_backup = discover_last_backup();
512
		if ($last_backup) {
513
			restore_backup("/cf/conf/backup/{$last_backup}");
514
			$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
515
			if (platform_booting()) {
516
				echo "\n\n ************** WARNING **************";
517
				echo "\n\n Configuration could not be validated. A previous configuration was restored. \n";
518
				echo "\n The failed configuration file has been saved as {$g['conf_path']}/config.xml.bad \n\n";
519
			}
520
		} else {
521
			log_error(gettext("Could not restore config.xml."));
522
		}
523
	} else {
524
		generate_config_cache($config);
525
	}
526

    
527
	unlock($lockkey);
528

    
529
	if ($write_config_only) {
530
		return $config;
531
	}
532

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

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

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

    
543
	return $config;
544
}
545

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

    
555

    
556
	/* Remove all additional packages */
557
	mwexec("/bin/sh /usr/local/sbin/{$g['product_name']}-upgrade " .
558
	    "-r ALL_PACKAGES");
559

    
560
	if (!$lock) {
561
		$lockkey = lock('config', LOCK_EX);
562
	}
563

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

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

    
578
	/* copy default configuration */
579
	copy("{$g['conf_default_path']}/config.xml",
580
	    "{$g['cf_conf_path']}/config.xml");
581

    
582
	disable_security_checks();
583

    
584
	/*
585
	   Let write_config know that we are awaiting reload of the current config
586
	   to factory defaults. Either the system is about to reboot, throwing away
587
	   the current in-memory config as it shuts down, or the in-memory config
588
	   is about to be reloaded on-the-fly by parse_config.
589

    
590
	   In both cases, we want to ensure that write_config does not flush the
591
	   in-memory config back to disk.
592
	*/
593
	$config['reset_factory_defaults'] = true;
594

    
595
	/* call the wizard */
596
	if ($reboot_required) {
597
		// If we need a reboot first then touch a different trigger file.
598
		touch("/conf/trigger_initial_wizard_after_reboot");
599
	} else {
600
		touch("/conf/trigger_initial_wizard");
601
	}
602
	if (!$lock) {
603
		unlock($lockkey);
604
	}
605
	setup_serial_port();
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

    
616
	backup_config();
617

    
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

    
631
	write_config(sprintf(gettext("Reverted to %s."), array_pop(explode("/", $conffile))), false);
632

    
633
	return 0;
634
}
635

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

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

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

    
647
	if (platform_booting()) {
648
		echo gettext("Installing configuration...") . "\n";
649
	} else {
650
		log_error(gettext("Installing configuration ...."));
651
	}
652

    
653
	$lockkey = lock('config', LOCK_EX);
654

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

    
657
	disable_security_checks();
658

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

    
664
	unlock($lockkey);
665

    
666
	return 0;
667
}
668

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

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

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

    
694
function config_validate($conffile) {
695

    
696
	global $g, $xmlerr;
697

    
698
	$xml_parser = xml_parser_create();
699

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

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

    
715
	fclose($fp);
716

    
717
	return true;
718
}
719

    
720
function cleanup_backupcache($lock = false) {
721
	global $config, $g;
722
	$i = false;
723

    
724
	$revisions = intval(is_numericint($config['system']['backupcount']) ? $config['system']['backupcount'] : $g['default_config_backup_count']);
725

    
726
	if (!$lock) {
727
		$lockkey = lock('config');
728
	}
729

    
730

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

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

    
803
	if (!$lock) {
804
		unlock($lockkey);
805
	}
806
}
807

    
808
function get_backups() {
809
	global $g;
810
	if (file_exists("{$g['cf_conf_path']}/backup/backup.cache")) {
811
		$confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache"));
812
		$bakvers = array_keys($confvers);
813
		$toreturn = array();
814
		sort($bakvers);
815
		// 	$bakvers = array_reverse($bakvers);
816
		foreach (array_reverse($bakvers) as $bakver) {
817
			$toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description'], 'version' => $confvers[$bakver]['version'], 'filesize' => $confvers[$bakver]['filesize']);
818
		}
819
	} else {
820
		return false;
821
	}
822
	$toreturn['versions'] = $bakvers;
823
	return $toreturn;
824
}
825

    
826
function backup_config() {
827
	global $config, $g;
828

    
829

    
830
	/* Create backup directory if needed */
831
	safe_mkdir("{$g['cf_conf_path']}/backup");
832
	if ($config['revision']['time'] == "") {
833
		$baktime = 0;
834
	} else {
835
		$baktime = $config['revision']['time'];
836
	}
837

    
838
	if ($config['revision']['description'] == "") {
839
		$bakdesc = "Unknown";
840
	} else {
841
		$bakdesc = $config['revision']['description'];
842
	}
843

    
844
	$bakver = ($config['version'] == "") ? "?" : $config['version'];
845
	$bakfilename = $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml';
846
	copy($g['cf_conf_path'] . '/config.xml', $bakfilename);
847

    
848
	if (file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
849
		$backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
850
	} else {
851
		$backupcache = array();
852
	}
853
	$backupcache[$baktime] = array('description' => $bakdesc, 'version' => $bakver, 'filesize' => filesize($bakfilename));
854
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
855
	fwrite($bakout, serialize($backupcache));
856
	fclose($bakout);
857
	pfSense_fsync("{$g['cf_conf_path']}/backup/backup.cache");
858

    
859

    
860
	return true;
861
}
862

    
863
function set_device_perms() {
864
	$devices = array(
865
		'pf' => array(
866
			'user' => 'root',
867
			'group' => 'proxy',
868
			'mode' => 0660),
869
		);
870

    
871
	foreach ($devices as $name => $attr) {
872
		$path = "/dev/$name";
873
		if (file_exists($path)) {
874
			chown($path, $attr['user']);
875
			chgrp($path, $attr['group']);
876
			chmod($path, $attr['mode']);
877
		}
878
	}
879
}
880

    
881
function get_config_user() {
882
	if (empty($_SESSION["Username"])) {
883
		$username = getenv("USER");
884
		if (empty($conuser) || $conuser == "root") {
885
			$username = "(system)";
886
		}
887
	} else {
888
		$username = $_SESSION["Username"];
889
	}
890

    
891
	if (!empty($_SERVER['REMOTE_ADDR'])) {
892
		$username .= '@' . $_SERVER['REMOTE_ADDR'];
893
	}
894

    
895
	return $username;
896
}
897

    
898
function make_config_revision_entry($desc = null, $override_user = null) {
899
	if (empty($override_user)) {
900
		$username = get_config_user();
901
	} else {
902
		$username = $override_user;
903
	}
904

    
905
	$revision = array();
906

    
907
	if (time() > mktime(0, 0, 0, 9, 1, 2004)) {     /* make sure the clock settings are plausible */
908
		$revision['time'] = time();
909
	}
910

    
911
	/* Log the running script so it's not entirely unlogged what changed */
912
	if ($desc == "Unknown") {
913
		$desc = sprintf(gettext("%s made unknown change"), $_SERVER['SCRIPT_NAME']);
914
	}
915
	if (!empty($desc)) {
916
		$revision['description'] = "{$username}: " . $desc;
917
	}
918
	$revision['username'] = $username;
919
	return $revision;
920
}
921

    
922
function pfSense_clear_globals() {
923
	global $config, $FilterIfList, $GatewaysList, $filterdns, $aliases, $aliastable;
924

    
925
	$error = error_get_last();
926

    
927
	// Errors generated by user code (diag_commands.php) are identified by path and not added to notices
928
	if ($error !== NULL && !preg_match('|^' . preg_quote($g['tmp_path_user_code']) . '/[^/]{1,16}$|', $error['file'])) {
929
		if (in_array($error['type'], array(E_ERROR, E_COMPILE_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR))) {
930
			$errorstr = "PHP ERROR: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}";
931
			print($errorstr);
932
			log_error($errorstr);
933
			file_notice("phperror", $errorstr, 'PHP errors');
934
		} else if ($error['type'] != E_NOTICE) {
935
			$errorstr = "PHP WARNING: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}";
936
			// XXX: comment out for now, should re-enable post-2.2
937
			//print($errorstr);
938
			//log_error($errorstr);
939
			//file_notice("phpwarning", $errorstr, 'PHP warning');
940
		}
941
	}
942

    
943
	if (isset($FilterIfList)) {
944
		unset($FilterIfList);
945
	}
946

    
947
	if (isset($GatewaysList)) {
948
		unset($GatewaysList);
949
	}
950

    
951
	/* Used for the hostname dns resolver */
952
	if (isset($filterdns)) {
953
		unset($filterdns);
954
	}
955

    
956
	/* Used for aliases and interface macros */
957
	if (isset($aliases)) {
958
		unset($aliases);
959
	}
960
	if (isset($aliastable)) {
961
		unset($aliastable);
962
	}
963

    
964
	unset($config);
965
}
966

    
967
register_shutdown_function('pfSense_clear_globals');
968

    
969
?>
(10-10/54)