Projet

Général

Profil

Télécharger (28,2 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / config.lib.inc @ 989d361e

1
<?php
2
/****h* pfSense/config
3
 * NAME
4
 *   config.lib.inc - Functions to manipulate config.xml
5
 * DESCRIPTION
6
 *   This include contains various config.xml specific functions.
7
 * HISTORY
8
 * $Id$
9
 ******
10

    
11
	config.lib.inc
12
	Ported from config.inc by Erik Kristensen
13
	Copyright (C) 2004-2010 Scott Ullrich
14
	All rights reserved.
15

    
16
	originally part of m0n0wall (http://m0n0.ch/wall)
17
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
18
	All rights reserved.
19

    
20
	Redistribution and use in source and binary forms, with or without
21
	modification, are permitted provided that the following conditions are met:
22

    
23
	1. Redistributions of source code must retain the above copyright notice,
24
	   this list of conditions and the following disclaimer.
25

    
26
	2. Redistributions in binary form must reproduce the above copyright
27
	   notice, this list of conditions and the following disclaimer in the
28
	   documentation and/or other materials provided with the distribution.
29

    
30
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
	POSSIBILITY OF SUCH DAMAGE.
40

    
41

    
42
	pfSense_BUILDER_BINARIES:	/sbin/mount	/sbin/sysctl	/sbin/umount	/sbin/halt	/sbin/fsck
43
	pfSense_MODULE:	config
44
*/
45

    
46
/****f* config/encrypted_configxml
47
 * NAME
48
 *   encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock.
49
 * INPUTS
50
 *   None
51
 * RESULT
52
 *   $config 	- rewrites config.xml without encryption
53
 ******/
54
function encrypted_configxml() {
55
	global $g, $config;
56

    
57
	if (!file_exists($g['conf_path'] . "/config.xml"))
58
		return;
59

    
60
	if (!$g['booting'])
61
		return;
62

    
63
	$configtxt = file_get_contents($g['conf_path'] . "/config.xml");			
64
	if(tagfile_deformat($configtxt, $configtxt, "config.xml")) {
65
		$fp = fopen('php://stdin', 'r');
66
		$data = "";
67
		echo "\n\n*** Encrypted config.xml detected ***\n";
68
		while($data == "") {
69
			echo "\nEnter the password to decrypt config.xml: ";
70
			$decrypt_password = chop(fgets($fp));
71
			$data = decrypt_data($configtxt, $decrypt_password);
72
			if(!strstr($data, "<pfsense>"))
73
				$data = "";
74
			if($data) {
75
				$fd = fopen($g['conf_path'] . "/config.xml.tmp", "w");
76
				fwrite($fd, $data);
77
				fclose($fd);
78
				exec("/bin/mv {$g['conf_path']}/config.xml.tmp {$g['conf_path']}/config.xml");
79
				echo "\n" . gettext("Config.xml unlocked.") . "\n";
80
				fclose($fp);
81
			} else {
82
				echo "\n" . gettext("Invalid password entered.  Please try again.") . "\n";
83
			}
84
		}
85
	}
86
}
87

    
88
/****f* config/parse_config
89
 * NAME
90
 *   parse_config - Read in config.cache or config.xml if needed and return $config array
91
 * INPUTS
92
 *   $parse       - boolean to force parse_config() to read config.xml and generate config.cache
93
 * RESULT
94
 *   $config      - array containing all configuration variables
95
 ******/
96
function parse_config($parse = false) {
97
	global $g, $config_parsed, $config_extra;
98

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

    
102
	if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) {
103
		$last_backup = discover_last_backup();
104
		if($last_backup) {
105
			log_error(gettext("No config.xml found, attempting last known config restore."));
106
			file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", "");
107
			restore_backup("{$g['conf_path']}/backup/{$last_backup}");
108
		} else {
109
			unlock($lockkey);
110
			die(gettext("Config.xml is corrupted and is 0 bytes.  Could not restore a previous backup."));
111
		}
112
	}
113

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

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

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

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

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

    
163
	alias_make_table($config);
164

    
165
	return $config;
166
}
167

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

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

    
192
function discover_last_backup() {
193
        $backups = explode("\n", `cd /cf/conf/backup && ls -ltr *.xml | awk '{print \$9}'`);
194
	$last_backup = "";
195
        foreach($backups as $backup)
196
        	if($backup)
197
	        	$last_backup = $backup;
198

    
199
        return $last_backup;
200
}
201

    
202
function restore_backup($file) {
203
	global $g;
204

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

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

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

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

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

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

    
280

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

    
289

    
290
EOD;
291
		}
292

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

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

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

    
311
	if ((refcount_reference(1000) > 1) && is_writable("/"))
312
		return;
313

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

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

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

    
345
	/* Do not trust $g['platform'] since this can be clobbered during factory reset. */
346
	$platform = trim(file_get_contents("/etc/platform"));
347
	/* do not umount on cdrom or pfSense platforms */
348
	if($platform == "cdrom" or $platform == "pfSense")
349
		return;
350

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

    
354
	if(isset($config['system']['nanobsd_force_rw']))
355
		return;
356

    
357
	if($g['booting'])
358
		return;
359

    
360
	clear_subsystem_dirty('mount');
361
	/* sync data, then force a remount of /cf */
362
	pfSense_sync();
363
	mwexec("/sbin/mount -u -r -f -o sync,noatime {$g['cf_path']}");
364
	mwexec("/sbin/mount -u -r -f -o sync,noatime /");
365
}
366

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

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

    
402
	// Save off config version
403
	$prev_version = $config['version'];
404
	
405
	include_once('auth.inc');
406
	include_once('upgrade_config.inc');
407
	if (file_exists("/etc/inc/upgrade_config_custom.inc"))
408
		include_once("upgrade_config_custom.inc");
409
	/* Loop and run upgrade_VER_to_VER() until we're at current version */
410
	while ($config['version'] < $g['latest_config']) {
411
		$cur = $config['version'] * 10;
412
		$next = $cur + 1;
413
		$migration_function = sprintf('upgrade_%03d_to_%03d', $cur, $next);
414
		if (function_exists($migration_function))
415
			$migration_function();
416
		$migration_function = "{$migration_function}_custom";
417
		if (function_exists($migration_function))
418
			$migration_function();
419
		$config['version'] = sprintf('%.1f', $next / 10);
420
		if($g['booting'])
421
			echo ".";
422
	}
423

    
424
	$now = date("H:i:s");
425
	log_error(sprintf(gettext("Ended Configuration upgrade at %s"), $now));
426

    
427
	if ($prev_version != $config['version'])
428
		write_config(sprintf(gettext('Upgraded config version level from %1$s to %2$s'), $prev_version, $config['version']));
429
}
430

    
431
/****f* config/safe_write_file
432
 * NAME
433
 *   safe_write_file - Write a file out atomically
434
 * DESCRIPTION
435
 *   safe_write_file() Writes a file out atomically by first writing to a
436
 *   temporary file of the same name but ending with the pid of the current
437
 *   process, them renaming the temporary file over the original.
438
 * INPUTS
439
 *   $filename  - string containing the filename of the file to write
440
 *   $content   - string containing the file content to write to file
441
 *   $force_binary      - boolean denoting whether we should force binary
442
 *   mode writing.
443
 * RESULT
444
 *   boolean - true if successful, false if not
445
 ******/
446
function safe_write_file($file, $content, $force_binary) {
447
	$tmp_file = $file . "." . getmypid();
448
	$write_mode = $force_binary ? "wb" : "w";
449

    
450
	$fd = fopen($tmp_file, $write_mode);
451
	if (!$fd) {
452
		// Unable to open temporary file for writing
453
		return false;
454
        }
455
	if (!fwrite($fd, $content)) {
456
		// Unable to write to temporary file
457
		fclose($fd);
458
		return false;
459
	}
460
	fflush($fd);
461
	fclose($fd);
462

    
463
	if (!rename($tmp_file, $file)) {
464
		// Unable to move temporary file to original
465
		@unlink($tmp_file);
466
		return false;
467
	}
468

    
469
	// Sync file before returning
470
	pfSense_sync();
471

    
472
	return true;
473
}
474

    
475
/****f* config/write_config
476
 * NAME
477
 *   write_config - Backup and write the firewall configuration.
478
 * DESCRIPTION
479
 *   write_config() handles backing up the current configuration,
480
 *   applying changes, and regenerating the configuration cache.
481
 * INPUTS
482
 *   $desc	- string containing the a description of configuration changes
483
 *   $backup	- boolean: do not back up current configuration if false.
484
 * RESULT
485
 *   null
486
 ******/
487
/* save the system configuration */
488
function write_config($desc="Unknown", $backup = true) {
489
	global $config, $g;
490

    
491
	/* TODO: Not sure what this was added for; commenting out
492
	 *       for now, since it was preventing config saving. */
493
	// $config = parse_config(true, false, false);
494
	
495
	/* Comment this check out for now. There aren't any current issues that
496
	 *   make this problematic, and it makes users think there is a problem
497
	 *   when one doesn't really exist.
498
	if($g['booting'])
499
		log_error("WARNING! Configuration written on bootup.  This can cause stray openvpn and load balancing items in config.xml");
500
	*/
501

    
502
	if (!empty($_SERVER['REMOTE_ADDR'])) {
503
		if (!session_id())
504
			@session_start();
505
		if (!empty($_SESSION['Username']) && ($_SESSION['Username'] != "admin")) {
506
			$user = getUserEntry($_SESSION['Username']);
507
			if (is_array($user) && userHasPrivilege($user, "user-config-readonly")) {
508
				session_commit();
509
				return false;
510
			}
511
		}
512
	}
513

    
514
	if (!isset($argc))
515
		session_commit();
516

    
517
	if($backup)
518
		backup_config();
519

    
520
	$config['revision'] = make_config_revision_entry($desc);
521

    
522
	conf_mount_rw();
523
	$lockkey = lock('config', LOCK_EX);
524

    
525
	/* generate configuration XML */
526
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
527

    
528
	/* write new configuration */
529
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
530
		log_error(gettext("WARNING: Config contents could not be save. Could not open file!"));
531
		unlock($lockkey);
532
		file_notice("config.xml", sprintf(gettext("Unable to open %s/config.xml for writing in write_config()%s"), $g['cf_conf_path'], "\n"));
533
		return -1;
534
	}
535
	
536
	cleanup_backupcache(true);
537

    
538
	/* re-read configuration */
539
	/* NOTE: We assume that the file can be parsed since we wrote it. */
540
	$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
541
	if ($config == -1) {
542
		copy("{$g['conf_path']}/config.xml", "{$g['conf_path']}/config.xml.bad");
543
		$last_backup = discover_last_backup();
544
		if ($last_backup) {
545
			restore_backup("/cf/conf/backup/{$last_backup}");
546
			$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
547
			if ($g['booting']) {
548
				echo "\n\n ************** WARNING **************";
549
				echo "\n\n Configuration could not be validated. A previous configuration was restored. \n";
550
				echo "\n The failed configuration file has been saved as {$g['conf_path']}/config.xml.bad \n\n";
551
			}
552
		} else
553
			log_error(gettext("Could not restore config.xml."));
554
	} else
555
		generate_config_cache($config);
556

    
557
	unlock($lockkey);
558

    
559
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
560

    
561
	/* tell kernel to sync fs data */
562
	conf_mount_ro();
563

    
564
	/* sync carp entries to other firewalls */
565
	carp_sync_client();
566

    
567
	if(is_dir("/usr/local/pkg/write_config")) {
568
		/* process packager manager custom rules */
569
		run_plugins("/usr/local/pkg/write_config/");
570
	}
571

    
572
	return $config;
573
}
574

    
575
/****f* config/reset_factory_defaults
576
 * NAME
577
 *   reset_factory_defaults - Reset the system to its default configuration.
578
 * RESULT
579
 *   integer	- indicates completion
580
 ******/
581
function reset_factory_defaults($lock = false) {
582
	global $g;
583

    
584
	conf_mount_rw();
585
	if (!$lock)
586
		$lockkey = lock('config', LOCK_EX);
587

    
588
	/* create conf directory, if necessary */
589
	safe_mkdir("{$g['cf_conf_path']}");
590

    
591
	/* clear out /conf */
592
	$dh = opendir($g['conf_path']);
593
	while ($filename = readdir($dh)) {
594
		if (($filename != ".") && ($filename != "..")) {
595
			unlink_if_exists($g['conf_path'] . "/" . $filename);
596
		}
597
	}
598
	closedir($dh);
599

    
600
	/* copy default configuration */
601
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
602

    
603
	disable_security_checks();
604

    
605
	/* call the wizard */
606
	touch("/conf/trigger_initial_wizard");
607
	if (!$lock)
608
		unlock($lockkey);
609
	conf_mount_ro();
610
	setup_serial_port();
611
	return 0;
612
}
613

    
614
function config_restore($conffile) {
615
	global $config, $g;
616

    
617
	if (!file_exists($conffile))
618
		return 1;
619

    
620
	backup_config();
621

    
622
	conf_mount_rw();
623
	
624
	$lockkey = lock('config', LOCK_EX);
625

    
626
	unlink_if_exists("{$g['tmp_path']}/config.cache");
627
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
628

    
629
	disable_security_checks();
630

    
631
	unlock($lockkey);
632

    
633
	$config = parse_config(true);
634

    
635
	conf_mount_ro();
636

    
637
	write_config(gettext("Reverted to") . " " . array_pop(explode("/", $conffile)) . ".", false);
638

    
639
	return 0;
640
}
641

    
642
function config_install($conffile) {
643
	global $config, $g;
644

    
645
	if (!file_exists($conffile))
646
		return 1;
647

    
648
	if (!config_validate("{$conffile}"))
649
		return 1;
650

    
651
	if($g['booting'] == true)
652
		echo gettext("Installing configuration...") . "\n";
653
	else
654
		log_error(gettext("Installing configuration ...."));
655

    
656
	conf_mount_rw();
657
	$lockkey = lock('config', LOCK_EX);
658

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

    
661
	disable_security_checks();
662

    
663
	/* unlink cache file if it exists */
664
	if(file_exists("{$g['tmp_path']}/config.cache"))
665
		unlink("{$g['tmp_path']}/config.cache");
666

    
667
	unlock($lockkey);
668
	conf_mount_ro();
669

    
670
    return 0;
671
}
672

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

    
686
/* Restores security checks.  Should be called after all succeed. */
687
function restore_security_checks() {
688
	global $g;
689
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
690
}
691

    
692
/* Returns status of security check temporary disable. */
693
function security_checks_disabled() {
694
	global $g;
695
	return file_exists("{$g['tmp_path']}/disable_security_checks");
696
}
697

    
698
function config_validate($conffile) {
699

    
700
	global $g, $xmlerr;
701

    
702
	$xml_parser = xml_parser_create();
703

    
704
	if (!($fp = fopen($conffile, "r"))) {
705
		$xmlerr = gettext("XML error: unable to open file");
706
		return false;
707
	}
708

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

    
719
	fclose($fp);
720

    
721
	return true;
722
}
723

    
724
function cleanup_backupcache($lock = false) {
725
	global $g;
726
	$i = false;
727

    
728
	$revisions = get_config_backup_count();
729

    
730
	if (!$lock)
731
		$lockkey = lock('config');
732

    
733
	conf_mount_rw();
734

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

    
747
	foreach($bakfiles as $backup) { // Check for backups in the directory not represented in the cache.
748
		$backupsize = filesize($backup);
749
		if($backupsize == 0) {
750
			unlink($backup);
751
			continue;
752
		}
753
		$tocheck = array_shift(explode('.', array_pop(explode('-', $backup))));
754
		if(!in_array($tocheck, $baktimes)) {
755
			$i = true;
756
			if($g['booting'])
757
				echo ".";
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
			if($newxml['version'] == "")
768
				$newxml['version'] = "?";
769
			$tocache[$tocheck] = array('description' => $newxml['revision']['description'], 'version' => $newxml['version'], 'filesize' => $backupsize);
770
		}
771
	}
772
	foreach($backups as $checkbak) {
773
		if(count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) {
774
			$newbaks[] = $checkbak;
775
		} else {
776
			$i = true;
777
			if($g['booting']) print " " . $tocheck . "r";
778
		}
779
	}
780
	foreach($newbaks as $todo) $tocache[$todo['time']] = array('description' => $todo['description'], 'version' => $todo['version'], 'filesize' => $todo['filesize']);
781
	if(is_int($revisions) and (count($tocache) > $revisions)) {
782
		$toslice = array_slice(array_keys($tocache), 0, $revisions);
783
		foreach($toslice as $sliced)
784
			$newcache[$sliced] = $tocache[$sliced];
785
		foreach($tocache as $version => $versioninfo) {
786
			if(!in_array($version, array_keys($newcache))) {
787
				unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml');
788
				//if($g['booting']) print " " . $tocheck . "d";
789
			}
790
		}
791
		$tocache = $newcache;
792
	}
793
	$bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
794
	fwrite($bakout, serialize($tocache));
795
	fclose($bakout);
796
	conf_mount_ro();
797

    
798
	if (!$lock)
799
		unlock($lockkey);
800
}
801

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

    
819
function backup_config() {
820
	global $config, $g;
821

    
822
	if($g['platform'] == "cdrom")
823
		return;
824

    
825
	conf_mount_rw();
826

    
827
	/* Create backup directory if needed */
828
	safe_mkdir("{$g['cf_conf_path']}/backup");
829

    
830
    if($config['revision']['time'] == "") {
831
            $baktime = 0;
832
    } else {
833
            $baktime = $config['revision']['time'];
834
    }
835
    if($config['revision']['description'] == "") {
836
            $bakdesc = "Unknown";
837
    } else {
838
            $bakdesc = $config['revision']['description'];
839
    }
840

    
841
	$bakver = ($config['version'] == "") ? "?" : $config['version'];
842
	$bakfilename = $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml';
843
	copy($g['cf_conf_path'] . '/config.xml', $bakfilename);
844
    if(file_exists($g['cf_conf_path'] . '/backup/backup.cache')) {
845
            $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache'));
846
    } else {
847
            $backupcache = array();
848
    }
849
	$backupcache[$baktime] = array('description' => $bakdesc, 'version' => $bakver, 'filesize' => filesize($bakfilename));
850
    $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w");
851
    fwrite($bakout, serialize($backupcache));
852
    fclose($bakout);
853

    
854
	conf_mount_ro();
855

    
856
	return true;
857
}
858

    
859
function set_device_perms() {
860
	$devices = array(
861
		'pf'	=> array(	'user'	=> 'root',
862
					'group'	=> 'proxy',
863
					'mode'	=> 0660),
864
		);
865

    
866
	foreach ($devices as $name => $attr) {
867
		$path = "/dev/$name";
868
		if (file_exists($path)) {
869
			chown($path, $attr['user']);
870
			chgrp($path, $attr['group']);
871
			chmod($path, $attr['mode']);
872
		}
873
	}
874
}
875

    
876
function get_config_user() {
877
	if (empty($_SESSION["Username"])) {
878
		$username = getenv("USER");
879
		if (empty($conuser) || $conuser == "root")
880
			$username = "(system)";
881
	} else
882
		$username = $_SESSION["Username"];
883

    
884
	if (!empty($_SERVER['REMOTE_ADDR']))
885
		$username .= '@' . $_SERVER['REMOTE_ADDR'];
886

    
887
	return $username;
888
}
889

    
890
function make_config_revision_entry($desc = null, $override_user = null) {
891
	if (empty($override_user))
892
		$username = get_config_user();
893
	else
894
		$username = $override_user;
895

    
896
	$revision = array();
897

    
898
	if (time() > mktime(0, 0, 0, 9, 1, 2004))       /* make sure the clock settings are plausible */
899
		$revision['time'] = time();
900

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

    
910
function get_config_backup_count() {
911
	global $config, $g;
912
	if (isset($config['system']['backupcount']) && is_numeric($config['system']['backupcount']) && ($config['system']['backupcount'] >= 0)) {
913
		return intval($config['system']['backupcount']);
914
	} elseif ($g['platform'] == "nanobsd") {
915
		return 5;
916
	} else {
917
		return 30;
918
	}
919
}
920

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

    
924
	if (isset($FilterIfList))
925
		unset($FilterIfList);
926

    
927
	if (isset($GatewaysList))
928
		unset($GatewaysList);
929

    
930
	/* Used for the hostname dns resolver */
931
	if (isset($filterdns))
932
		unset($filterdns);
933

    
934
	/* Used for aliases and interface macros */
935
	if (isset($aliases))
936
		unset($aliases);
937
	if (isset($aliastable))
938
		unset($aliastable);
939

    
940
	unset($config);
941
}
942

    
943
register_shutdown_function('pfSense_clear_globals');
944

    
945
?>
(13-13/67)