Projet

Général

Profil

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

univnautes / etc / inc / config.lib.inc @ b5e8282d

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
	parse_config(true);
277

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

    
281

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

    
290

    
291
EOD;
292
		}
293

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
473
	return true;
474
}
475

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

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

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

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

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

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

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

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

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

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

    
558
	unlock($lockkey);
559

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

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

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

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

    
573
	return $config;
574
}
575

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

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

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

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

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

    
604
	disable_security_checks();
605

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

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

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

    
621
	backup_config();
622

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

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

    
630
	disable_security_checks();
631

    
632
	unlock($lockkey);
633

    
634
	$config = parse_config(true);
635

    
636
	conf_mount_ro();
637

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

    
640
	return 0;
641
}
642

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

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

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

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

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

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

    
662
	disable_security_checks();
663

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

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

    
671
    return 0;
672
}
673

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

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

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

    
699
function config_validate($conffile) {
700

    
701
	global $g, $xmlerr;
702

    
703
	$xml_parser = xml_parser_create();
704

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

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

    
720
	fclose($fp);
721

    
722
	return true;
723
}
724

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

    
729
	$revisions = get_config_backup_count();
730

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

    
734
	conf_mount_rw();
735

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

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

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

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

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

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

    
826
	conf_mount_rw();
827

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

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

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

    
855
	conf_mount_ro();
856

    
857
	return true;
858
}
859

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

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

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

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

    
888
	return $username;
889
}
890

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

    
897
	$revision = array();
898

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

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

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

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

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

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

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

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

    
941
	unset($config);
942
}
943

    
944
register_shutdown_function('pfSense_clear_globals');
945

    
946
?>
(13-13/67)