Project

General

Profile

Download (27.7 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
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
353
	while ($config['version'] < $g['latest_config']) {
354
		$cur = $config['version'] * 10;
355
		$next = $cur + 1;
356
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
357
		if (function_exists($migration_function)) {
358
			$migration_function();
359
		}
360
		$migration_function = "{$migration_function}_custom";
361
		if (function_exists($migration_function)) {
362
			$migration_function();
363
		}
364
		$config['version'] = sprintf('%.1f', $next / 10);
365
		if (platform_booting()) {
366
			echo ".";
367
		}
368
	}
369

    
370
	additional_config_upgrade();
371

    
372
	$now = date("H:i:s");
373
	log_error(sprintf(gettext("Ended Configuration upgrade at %s"), $now));
374

    
375
	if ($prev_version != $config['version']) {
376
		write_config(sprintf(gettext('Upgraded config version level from %1$s to %2$s'), $prev_version, $config['version']));
377
	}
378
}
379

    
380
/****f* config/safe_write_file
381
 * NAME
382
 *   safe_write_file - Write a file out atomically
383
 * DESCRIPTION
384
 *   safe_write_file() Writes a file out atomically by first writing to a
385
 *   temporary file of the same name but ending with the pid of the current
386
 *   process, them renaming the temporary file over the original.
387
 * INPUTS
388
 *   $filename  - string containing the filename of the file to write
389
 *   $content   - string or array containing the file content to write to file
390
 *   $force_binary      - boolean denoting whether we should force binary
391
 *   mode writing.
392
 * RESULT
393
 *   boolean - true if successful, false if not
394
 ******/
395
function safe_write_file($file, $content, $force_binary = false) {
396
	$tmp_file = $file . "." . getmypid();
397
	$write_mode = $force_binary ? "wb" : "w";
398

    
399
	$fd = fopen($tmp_file, $write_mode);
400
	if (!$fd) {
401
		// Unable to open temporary file for writing
402
		return false;
403
	}
404
	if (is_array($content)) {
405
		foreach ($content as $line) {
406
			if (!fwrite($fd, $line . "\n")) {
407
				// Unable to write to temporary file
408
				fclose($fd);
409
				return false;
410
			}
411
		}
412
	} elseif (!fwrite($fd, $content)) {
413
		// Unable to write to temporary file
414
		fclose($fd);
415
		return false;
416
	}
417
	fflush($fd);
418
	fclose($fd);
419

    
420
	if (!pfSense_fsync($tmp_file) || !rename($tmp_file, $file)) {
421
		// Unable to move temporary file to original
422
		@unlink($tmp_file);
423
		return false;
424
	}
425

    
426
	// Sync file before returning
427
	return pfSense_fsync($file);
428
}
429

    
430
/****f* config/write_config
431
 * NAME
432
 *   write_config - Backup and write the firewall configuration.
433
 * DESCRIPTION
434
 *   write_config() handles backing up the current configuration,
435
 *   applying changes, and regenerating the configuration cache.
436
 * INPUTS
437
 *   $desc	- string containing the a description of configuration changes
438
 *   $backup	- boolean: do not back up current configuration if false.
439
 *   $write_config_only	- boolean: do not sync or reload anything; just save the configuration if true.
440
 * RESULT
441
 *   null
442
 ******/
443
/* save the system configuration */
444
function write_config($desc="Unknown", $backup = true, $write_config_only = false) {
445
	global $config, $g;
446

    
447
	if (!empty($_SERVER['REMOTE_ADDR'])) {
448
		@phpsession_begin();
449
		if (!empty($_SESSION['Username']) && ($_SESSION['Username'] != "admin")) {
450
			$user = getUserEntry($_SESSION['Username']);
451
			if (is_array($user) && userHasPrivilege($user, "user-config-readonly")) {
452
				syslog(LOG_AUTHPRIV, sprintf(gettext("Save config permission denied by the 'User - Config: Deny Config Write' permission for user '%s'."), $_SESSION['Username']));
453
				phpsession_end(true);
454
				return false;
455
			}
456
		}
457
		if (!isset($argc)) {
458
			phpsession_end(true);
459
		}
460
	}
461

    
462
	if (isset($config['reset_factory_defaults'])) {
463
		/*
464
		   We have put a default config.xml on disk and are about to reboot
465
		   or reload it. Do not let any system or package code try to save
466
		   state to config because that would overwrite the default config
467
		   with the running config.
468
		*/
469
		return false;
470
	}
471

    
472
	if ($backup) {
473
		backup_config();
474
	}
475

    
476
	$config['revision'] = make_config_revision_entry($desc);
477

    
478
	$lockkey = lock('config', LOCK_EX);
479

    
480
	/* generate configuration XML */
481
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
482

    
483
	/* write new configuration */
484
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig)) {
485
		log_error(gettext("WARNING: Config contents could not be saved. Could not open file!"));
486
		unlock($lockkey);
487
		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"));
488
		return -1;
489
	}
490

    
491
	cleanup_backupcache(true);
492

    
493
	/* re-read configuration */
494
	/* NOTE: We assume that the file can be parsed since we wrote it. */
495
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
496
	if ($config == -1) {
497
		copy("{$g['conf_path']}/config.xml", "{$g['conf_path']}/config.xml.bad");
498
		$last_backup = discover_last_backup();
499
		if ($last_backup) {
500
			restore_backup("/cf/conf/backup/{$last_backup}");
501
			$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
502
			if (platform_booting()) {
503
				echo "\n\n ************** WARNING **************";
504
				echo "\n\n Configuration could not be validated. A previous configuration was restored. \n";
505
				echo "\n The failed configuration file has been saved as {$g['conf_path']}/config.xml.bad \n\n";
506
			}
507
		} else {
508
			log_error(gettext("Could not restore config.xml."));
509
		}
510
	} else {
511
		generate_config_cache($config);
512
	}
513

    
514
	unlock($lockkey);
515

    
516
	if ($write_config_only) {
517
		return $config;
518
	}
519

    
520
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
521

    
522
	/* sync carp entries to other firewalls */
523
	carp_sync_client();
524

    
525
	if (is_dir("/usr/local/pkg/write_config")) {
526
		/* process packager manager custom rules */
527
		run_plugins("/usr/local/pkg/write_config/");
528
	}
529

    
530
	return $config;
531
}
532

    
533
/****f* config/reset_factory_defaults
534
 * NAME
535
 *   reset_factory_defaults - Reset the system to its default configuration.
536
 * RESULT
537
 *   integer	- indicates completion
538
 ******/
539
function reset_factory_defaults($lock = false, $reboot_required = true) {
540
	global $config, $g;
541

    
542

    
543
	/* Remove all additional packages */
544
	mwexec("/bin/sh /usr/local/sbin/{$g['product_name']}-upgrade " .
545
	    "-r ALL_PACKAGES");
546

    
547
	if (!$lock) {
548
		$lockkey = lock('config', LOCK_EX);
549
	}
550

    
551
	/* create conf directory, if necessary */
552
	safe_mkdir($g['cf_conf_path']);
553

    
554
	/* clear out /conf */
555
	$dh = opendir($g['conf_path']);
556
	while ($filename = readdir($dh)) {
557
		if (($filename != ".") && ($filename != "..") &&
558
		    (!is_dir($g['conf_path'] . "/" . $filename))) {
559
			unlink_if_exists($g['conf_path'] . "/" . $filename);
560
		}
561
	}
562
	closedir($dh);
563
	unlink_if_exists($g['tmp_path'] . "/config.cache");
564

    
565
	/* copy default configuration */
566
	copy("{$g['conf_default_path']}/config.xml",
567
	    "{$g['cf_conf_path']}/config.xml");
568

    
569
	disable_security_checks();
570

    
571
	/*
572
	   Let write_config know that we are awaiting reload of the current config
573
	   to factory defaults. Either the system is about to reboot, throwing away
574
	   the current in-memory config as it shuts down, or the in-memory config
575
	   is about to be reloaded on-the-fly by parse_config.
576

    
577
	   In both cases, we want to ensure that write_config does not flush the
578
	   in-memory config back to disk.
579
	*/
580
	$config['reset_factory_defaults'] = true;
581

    
582
	/* call the wizard */
583
	if ($reboot_required) {
584
		// If we need a reboot first then touch a different trigger file.
585
		touch("/conf/trigger_initial_wizard_after_reboot");
586
	} else {
587
		touch("/conf/trigger_initial_wizard");
588
	}
589
	if (!$lock) {
590
		unlock($lockkey);
591
	}
592
	setup_serial_port();
593
	return 0;
594
}
595

    
596
function config_restore($conffile) {
597
	global $config, $g;
598

    
599
	if (!file_exists($conffile)) {
600
		return 1;
601
	}
602

    
603
	backup_config();
604

    
605

    
606
	$lockkey = lock('config', LOCK_EX);
607

    
608
	unlink_if_exists("{$g['tmp_path']}/config.cache");
609
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
610

    
611
	disable_security_checks();
612

    
613
	unlock($lockkey);
614

    
615
	$config = parse_config(true);
616

    
617

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

    
620
	return 0;
621
}
622

    
623
function config_install($conffile) {
624
	global $config, $g;
625

    
626
	if (!file_exists($conffile)) {
627
		return 1;
628
	}
629

    
630
	if (!config_validate("{$conffile}")) {
631
		return 1;
632
	}
633

    
634
	if (platform_booting()) {
635
		echo gettext("Installing configuration...") . "\n";
636
	} else {
637
		log_error(gettext("Installing configuration ...."));
638
	}
639

    
640
	$lockkey = lock('config', LOCK_EX);
641

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

    
644
	disable_security_checks();
645

    
646
	/* unlink cache file if it exists */
647
	if (file_exists("{$g['tmp_path']}/config.cache")) {
648
		unlink("{$g['tmp_path']}/config.cache");
649
	}
650

    
651
	unlock($lockkey);
652

    
653
	return 0;
654
}
655

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

    
669
/* Restores security checks.  Should be called after all succeed. */
670
function restore_security_checks() {
671
	global $g;
672
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
673
}
674

    
675
/* Returns status of security check temporary disable. */
676
function security_checks_disabled() {
677
	global $g;
678
	return file_exists("{$g['tmp_path']}/disable_security_checks");
679
}
680

    
681
function config_validate($conffile) {
682

    
683
	global $g, $xmlerr;
684

    
685
	$xml_parser = xml_parser_create();
686

    
687
	if (!($fp = fopen($conffile, "r"))) {
688
		$xmlerr = gettext("XML error: unable to open file");
689
		return false;
690
	}
691

    
692
	while ($data = fread($fp, 4096)) {
693
		if (!xml_parse($xml_parser, $data, feof($fp))) {
694
			$xmlerr = sprintf(gettext('%1$s at line %2$d'),
695
						xml_error_string(xml_get_error_code($xml_parser)),
696
						xml_get_current_line_number($xml_parser));
697
			return false;
698
		}
699
	}
700
	xml_parser_free($xml_parser);
701

    
702
	fclose($fp);
703

    
704
	return true;
705
}
706

    
707
function cleanup_backupcache($lock = false) {
708
	global $config, $g;
709
	$i = false;
710

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

    
713
	if (!$lock) {
714
		$lockkey = lock('config');
715
	}
716

    
717

    
718
	$backups = get_backups();
719
	if ($backups) {
720
		$baktimes = $backups['versions'];
721
		unset($backups['versions']);
722
	} else {
723
		$backups = array();
724
		$baktimes = array();
725
	}
726
	$newbaks = array();
727
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
728
	$tocache = array();
729

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

    
790
	if (!$lock) {
791
		unlock($lockkey);
792
	}
793
}
794

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

    
813
function backup_config() {
814
	global $config, $g;
815

    
816

    
817
	/* Create backup directory if needed */
818
	safe_mkdir("{$g['cf_conf_path']}/backup");
819
	if ($config['revision']['time'] == "") {
820
		$baktime = 0;
821
	} else {
822
		$baktime = $config['revision']['time'];
823
	}
824

    
825
	if ($config['revision']['description'] == "") {
826
		$bakdesc = "Unknown";
827
	} else {
828
		$bakdesc = $config['revision']['description'];
829
	}
830

    
831
	$bakver = ($config['version'] == "") ? "?" : $config['version'];
832
	$bakfilename = $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml';
833
	copy($g['cf_conf_path'] . '/config.xml', $bakfilename);
834

    
835
	if (file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
836
		$backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
837
	} else {
838
		$backupcache = array();
839
	}
840
	$backupcache[$baktime] = array('description' => $bakdesc, 'version' => $bakver, 'filesize' => filesize($bakfilename));
841
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
842
	fwrite($bakout, serialize($backupcache));
843
	fclose($bakout);
844
	pfSense_fsync("{$g['cf_conf_path']}/backup/backup.cache");
845

    
846

    
847
	return true;
848
}
849

    
850
function set_device_perms() {
851
	$devices = array(
852
		'pf' => array(
853
			'user' => 'root',
854
			'group' => 'proxy',
855
			'mode' => 0660),
856
		);
857

    
858
	foreach ($devices as $name => $attr) {
859
		$path = "/dev/$name";
860
		if (file_exists($path)) {
861
			chown($path, $attr['user']);
862
			chgrp($path, $attr['group']);
863
			chmod($path, $attr['mode']);
864
		}
865
	}
866
}
867

    
868
function get_config_user() {
869
	if (empty($_SESSION["Username"])) {
870
		$username = getenv("USER");
871
		if (empty($conuser) || $conuser == "root") {
872
			$username = "(system)";
873
		}
874
	} else {
875
		$username = $_SESSION["Username"];
876
	}
877

    
878
	if (!empty($_SERVER['REMOTE_ADDR'])) {
879
		$username .= '@' . $_SERVER['REMOTE_ADDR'];
880
	}
881

    
882
	return $username;
883
}
884

    
885
function make_config_revision_entry($desc = null, $override_user = null) {
886
	if (empty($override_user)) {
887
		$username = get_config_user();
888
	} else {
889
		$username = $override_user;
890
	}
891

    
892
	$revision = array();
893

    
894
	if (time() > mktime(0, 0, 0, 9, 1, 2004)) {     /* make sure the clock settings are plausible */
895
		$revision['time'] = time();
896
	}
897

    
898
	/* Log the running script so it's not entirely unlogged what changed */
899
	if ($desc == "Unknown") {
900
		$desc = sprintf(gettext("%s made unknown change"), $_SERVER['SCRIPT_NAME']);
901
	}
902
	if (!empty($desc)) {
903
		$revision['description'] = "{$username}: " . $desc;
904
	}
905
	$revision['username'] = $username;
906
	return $revision;
907
}
908

    
909
function pfSense_clear_globals() {
910
	global $config, $FilterIfList, $GatewaysList, $filterdns, $aliases, $aliastable;
911

    
912
	$error = error_get_last();
913

    
914
	// Errors generated by user code (diag_commands.php) are identified by path and not added to notices
915
	if ($error !== NULL && !preg_match('|^' . preg_quote($g['tmp_path_user_code']) . '/[^/]{1,16}$|', $error['file'])) {
916
		if (in_array($error['type'], array(E_ERROR, E_COMPILE_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR))) {
917
			$errorstr = "PHP ERROR: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}";
918
			print($errorstr);
919
			log_error($errorstr);
920
			file_notice("phperror", $errorstr, 'PHP errors');
921
		} else if ($error['type'] != E_NOTICE) {
922
			$errorstr = "PHP WARNING: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}";
923
			// XXX: comment out for now, should re-enable post-2.2
924
			//print($errorstr);
925
			//log_error($errorstr);
926
			//file_notice("phpwarning", $errorstr, 'PHP warning');
927
		}
928
	}
929

    
930
	if (isset($FilterIfList)) {
931
		unset($FilterIfList);
932
	}
933

    
934
	if (isset($GatewaysList)) {
935
		unset($GatewaysList);
936
	}
937

    
938
	/* Used for the hostname dns resolver */
939
	if (isset($filterdns)) {
940
		unset($filterdns);
941
	}
942

    
943
	/* Used for aliases and interface macros */
944
	if (isset($aliases)) {
945
		unset($aliases);
946
	}
947
	if (isset($aliastable)) {
948
		unset($aliastable);
949
	}
950

    
951
	unset($config);
952
}
953

    
954
register_shutdown_function('pfSense_clear_globals');
955

    
956
?>
(10-10/54)