Projet

Général

Profil

Télécharger (27,7 ko) Statistiques
| Branche: | Tag: | Révision:

univnautes / etc / inc / config.lib.inc @ 89adb2f3

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
	$config = parse_config(true);
278

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

    
282

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

    
291

    
292
EOD;
293
		}
294

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
474
	return true;
475
}
476

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

    
493
	if (!empty($_SERVER['REMOTE_ADDR'])) {
494
		if (!session_id())
495
			@session_start();
496
		if (!empty($_SESSION['Username']) && ($_SESSION['Username'] != "admin")) {
497
			$user = getUserEntry($_SESSION['Username']);
498
			if (is_array($user) && userHasPrivilege($user, "user-config-readonly")) {
499
				session_commit();
500
				return false;
501
			}
502
		}
503
	}
504

    
505
	if (!isset($argc))
506
		session_commit();
507

    
508
	if($backup)
509
		backup_config();
510

    
511
	$config['revision'] = make_config_revision_entry($desc);
512

    
513
	conf_mount_rw();
514
	$lockkey = lock('config', LOCK_EX);
515

    
516
	/* generate configuration XML */
517
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
518

    
519
	/* write new configuration */
520
	if (!safe_write_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
521
		log_error(gettext("WARNING: Config contents could not be save. Could not open file!"));
522
		unlock($lockkey);
523
		file_notice("config.xml", sprintf(gettext("Unable to open %s/config.xml for writing in write_config()%s"), $g['cf_conf_path'], "\n"));
524
		return -1;
525
	}
526
	
527
	cleanup_backupcache(true);
528

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

    
548
	unlock($lockkey);
549

    
550
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
551

    
552
	/* tell kernel to sync fs data */
553
	conf_mount_ro();
554

    
555
	/* sync carp entries to other firewalls */
556
	carp_sync_client();
557

    
558
	if(is_dir("/usr/local/pkg/write_config")) {
559
		/* process packager manager custom rules */
560
		run_plugins("/usr/local/pkg/write_config/");
561
	}
562

    
563
	return $config;
564
}
565

    
566
/****f* config/reset_factory_defaults
567
 * NAME
568
 *   reset_factory_defaults - Reset the system to its default configuration.
569
 * RESULT
570
 *   integer	- indicates completion
571
 ******/
572
function reset_factory_defaults($lock = false) {
573
	global $g;
574

    
575
	conf_mount_rw();
576
	if (!$lock)
577
		$lockkey = lock('config', LOCK_EX);
578

    
579
	/* create conf directory, if necessary */
580
	safe_mkdir("{$g['cf_conf_path']}");
581

    
582
	/* clear out /conf */
583
	$dh = opendir($g['conf_path']);
584
	while ($filename = readdir($dh)) {
585
		if (($filename != ".") && ($filename != "..")) {
586
			unlink_if_exists($g['conf_path'] . "/" . $filename);
587
		}
588
	}
589
	closedir($dh);
590

    
591
	/* copy default configuration */
592
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
593

    
594
	disable_security_checks();
595

    
596
	/* call the wizard */
597
	touch("/conf/trigger_initial_wizard");
598
	if (!$lock)
599
		unlock($lockkey);
600
	conf_mount_ro();
601
	setup_serial_port();
602
	return 0;
603
}
604

    
605
function config_restore($conffile) {
606
	global $config, $g;
607

    
608
	if (!file_exists($conffile))
609
		return 1;
610

    
611
	backup_config();
612

    
613
	conf_mount_rw();
614
	
615
	$lockkey = lock('config', LOCK_EX);
616

    
617
	unlink_if_exists("{$g['tmp_path']}/config.cache");
618
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
619

    
620
	disable_security_checks();
621

    
622
	unlock($lockkey);
623

    
624
	$config = parse_config(true);
625

    
626
	conf_mount_ro();
627

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

    
630
	return 0;
631
}
632

    
633
function config_install($conffile) {
634
	global $config, $g;
635

    
636
	if (!file_exists($conffile))
637
		return 1;
638

    
639
	if (!config_validate("{$conffile}"))
640
		return 1;
641

    
642
	if($g['booting'] == true)
643
		echo gettext("Installing configuration...") . "\n";
644
	else
645
		log_error(gettext("Installing configuration ...."));
646

    
647
	conf_mount_rw();
648
	$lockkey = lock('config', LOCK_EX);
649

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

    
652
	disable_security_checks();
653

    
654
	/* unlink cache file if it exists */
655
	if(file_exists("{$g['tmp_path']}/config.cache"))
656
		unlink("{$g['tmp_path']}/config.cache");
657

    
658
	unlock($lockkey);
659
	conf_mount_ro();
660

    
661
    return 0;
662
}
663

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

    
677
/* Restores security checks.  Should be called after all succeed. */
678
function restore_security_checks() {
679
	global $g;
680
	unlink_if_exists("{$g['tmp_path']}/disable_security_checks");
681
}
682

    
683
/* Returns status of security check temporary disable. */
684
function security_checks_disabled() {
685
	global $g;
686
	return file_exists("{$g['tmp_path']}/disable_security_checks");
687
}
688

    
689
function config_validate($conffile) {
690

    
691
	global $g, $xmlerr;
692

    
693
	$xml_parser = xml_parser_create();
694

    
695
	if (!($fp = fopen($conffile, "r"))) {
696
		$xmlerr = gettext("XML error: unable to open file");
697
		return false;
698
	}
699

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

    
710
	fclose($fp);
711

    
712
	return true;
713
}
714

    
715
function cleanup_backupcache($lock = false) {
716
	global $g;
717
	$i = false;
718

    
719
	$revisions = get_config_backup_count();
720

    
721
	if (!$lock)
722
		$lockkey = lock('config');
723

    
724
	conf_mount_rw();
725

    
726
	$backups = get_backups();
727
	if ($backups) {
728
		$baktimes = $backups['versions'];
729
		unset($backups['versions']);
730
	} else {
731
		$backups = array();
732
		$baktimes = array();
733
	}
734
	$newbaks = array();
735
	$bakfiles = glob($g['cf_conf_path'] . "/backup/config-*");
736
	$tocache = array();
737

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

    
789
	if (!$lock)
790
		unlock($lockkey);
791
}
792

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

    
810
function backup_config() {
811
	global $config, $g;
812

    
813
	if($g['platform'] == "cdrom")
814
		return;
815

    
816
	conf_mount_rw();
817

    
818
	/* Create backup directory if needed */
819
	safe_mkdir("{$g['cf_conf_path']}/backup");
820

    
821
    if($config['revision']['time'] == "") {
822
            $baktime = 0;
823
    } else {
824
            $baktime = $config['revision']['time'];
825
    }
826
    if($config['revision']['description'] == "") {
827
            $bakdesc = "Unknown";
828
    } else {
829
            $bakdesc = $config['revision']['description'];
830
    }
831

    
832
	$bakver = ($config['version'] == "") ? "?" : $config['version'];
833
	$bakfilename = $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml';
834
	copy($g['cf_conf_path'] . '/config.xml', $bakfilename);
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

    
845
	conf_mount_ro();
846

    
847
	return true;
848
}
849

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

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

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

    
875
	if (!empty($_SERVER['REMOTE_ADDR']))
876
		$username .= '@' . $_SERVER['REMOTE_ADDR'];
877

    
878
	return $username;
879
}
880

    
881
function make_config_revision_entry($desc = null, $override_user = null) {
882
	if (empty($override_user))
883
		$username = get_config_user();
884
	else
885
		$username = $override_user;
886

    
887
	$revision = array();
888

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

    
892
	/* Log the running script so it's not entirely unlogged what changed */
893
	if ($desc == "Unknown")
894
		$desc = sprintf(gettext("%s made unknown change"), $_SERVER['SCRIPT_NAME']);
895
	if (!empty($desc))
896
		$revision['description'] = "{$username}: " . $desc;
897
	$revision['username'] = $username;
898
	return $revision;
899
}
900

    
901
function get_config_backup_count() {
902
	global $config, $g;
903
	if (isset($config['system']['backupcount']) && is_numeric($config['system']['backupcount']) && ($config['system']['backupcount'] >= 0)) {
904
		return intval($config['system']['backupcount']);
905
	} elseif ($g['platform'] == "nanobsd") {
906
		return 5;
907
	} else {
908
		return 30;
909
	}
910
}
911

    
912
function pfSense_clear_globals() {
913
	global $config, $FilterIfList, $GatewaysList, $filterdns, $aliases, $aliastable;
914

    
915
	if (isset($FilterIfList))
916
		unset($FilterIfList);
917

    
918
	if (isset($GatewaysList))
919
		unset($GatewaysList);
920

    
921
	/* Used for the hostname dns resolver */
922
	if (isset($filterdns))
923
		unset($filterdns);
924

    
925
	/* Used for aliases and interface macros */
926
	if (isset($aliases))
927
		unset($aliases);
928
	if (isset($aliastable))
929
		unset($aliastable);
930

    
931
	unset($config);
932
}
933

    
934
register_shutdown_function('pfSense_clear_globals');
935

    
936
?>
(13-13/67)