Projet

Général

Profil

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

univnautes / etc / inc / config.lib.inc @ 692c21fd

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 = glob('/cf/conf/backup/*.xml');
194
	$last_backup = "";
195
	$last_mtime = 0;
196
	foreach($backups as $backup) {
197
		if(filemtime($backup) > $last_mtime) {
198
			$last_mtime = filemtime($backup);
199
			$last_backup = $backup;
200
		}
201
	}
202

    
203
	return basename($last_backup);
204
}
205

    
206
function restore_backup($file) {
207
	global $g;
208

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

    
220
/****f* config/parse_config_bootup
221
 * NAME
222
 *   parse_config_bootup - Bootup-specific configuration checks.
223
 * RESULT
224
 *   null
225
 ******/
226
function parse_config_bootup() {
227
	global $config, $g;
228

    
229
	if($g['booting'])
230
		echo ".";
231

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

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

    
281
	$config = parse_config(true);
282

    
283
	if ((float)$config['version'] > (float)$g['latest_config']) {
284
		echo <<<EOD
285

    
286

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

    
295

    
296
EOD;
297
		}
298

    
299
	/* make alias table (for faster lookups) */
300
	alias_make_table($config);
301
}
302

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

    
313
	/* do not mount on cdrom platform */
314
	if($g['platform'] == "cdrom" or $g['platform'] == "pfSense")
315
		return;
316

    
317
	if ((refcount_reference(1000) > 1) && is_writable("/"))
318
		return;
319

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

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

    
342
/****f* config/conf_mount_ro
343
 * NAME
344
 *   conf_mount_ro - Mount filesystems readonly.
345
 * RESULT
346
 *   null
347
 ******/
348
function conf_mount_ro() {
349
	global $g, $config;
350

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

    
357
	if (refcount_unreference(1000) > 0)
358
		return;
359

    
360
	if(isset($config['system']['nanobsd_force_rw']))
361
		return;
362

    
363
	if($g['booting'])
364
		return;
365

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

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

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

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

    
430
	$now = date("H:i:s");
431
	log_error(sprintf(gettext("Ended Configuration upgrade at %s"), $now));
432

    
433
	if ($prev_version != $config['version'])
434
		write_config(sprintf(gettext('Upgraded config version level from %1$s to %2$s'), $prev_version, $config['version']));
435
}
436

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

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

    
469
	if (!rename($tmp_file, $file)) {
470
		// Unable to move temporary file to original
471
		@unlink($tmp_file);
472
		return false;
473
	}
474

    
475
	// Sync file before returning
476
	pfSense_sync();
477

    
478
	return true;
479
}
480

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

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

    
509
	if (!isset($argc))
510
		session_commit();
511

    
512
	if($backup)
513
		backup_config();
514

    
515
	$config['revision'] = make_config_revision_entry($desc);
516

    
517
	conf_mount_rw();
518
	$lockkey = lock('config', LOCK_EX);
519

    
520
	/* generate configuration XML */
521
	$xmlconfig = dump_xml_config($config, $g['xml_rootobj']);
522

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

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

    
552
	unlock($lockkey);
553

    
554
	unlink_if_exists("/usr/local/pkg/pf/carp_sync_client.php");
555

    
556
	/* tell kernel to sync fs data */
557
	conf_mount_ro();
558

    
559
	/* sync carp entries to other firewalls */
560
	carp_sync_client();
561

    
562
	if(is_dir("/usr/local/pkg/write_config")) {
563
		/* process packager manager custom rules */
564
		run_plugins("/usr/local/pkg/write_config/");
565
	}
566

    
567
	return $config;
568
}
569

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

    
579
	conf_mount_rw();
580
	if (!$lock)
581
		$lockkey = lock('config', LOCK_EX);
582

    
583
	/* create conf directory, if necessary */
584
	safe_mkdir("{$g['cf_conf_path']}");
585

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

    
595
	/* copy default configuration */
596
	copy("{$g['conf_default_path']}/config.xml", "{$g['conf_path']}/config.xml");
597

    
598
	disable_security_checks();
599

    
600
	/* call the wizard */
601
	touch("/conf/trigger_initial_wizard");
602
	if (!$lock)
603
		unlock($lockkey);
604
	conf_mount_ro();
605
	setup_serial_port();
606
	return 0;
607
}
608

    
609
function config_restore($conffile) {
610
	global $config, $g;
611

    
612
	if (!file_exists($conffile))
613
		return 1;
614

    
615
	backup_config();
616

    
617
	conf_mount_rw();
618
	
619
	$lockkey = lock('config', LOCK_EX);
620

    
621
	unlink_if_exists("{$g['tmp_path']}/config.cache");
622
	copy($conffile, "{$g['cf_conf_path']}/config.xml");
623

    
624
	disable_security_checks();
625

    
626
	unlock($lockkey);
627

    
628
	$config = parse_config(true);
629

    
630
	conf_mount_ro();
631

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

    
634
	return 0;
635
}
636

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

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

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

    
646
	if($g['booting'] == true)
647
		echo gettext("Installing configuration...") . "\n";
648
	else
649
		log_error(gettext("Installing configuration ...."));
650

    
651
	conf_mount_rw();
652
	$lockkey = lock('config', LOCK_EX);
653

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

    
656
	disable_security_checks();
657

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

    
662
	unlock($lockkey);
663
	conf_mount_ro();
664

    
665
    return 0;
666
}
667

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

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

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

    
693
function config_validate($conffile) {
694

    
695
	global $g, $xmlerr;
696

    
697
	$xml_parser = xml_parser_create();
698

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

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

    
714
	fclose($fp);
715

    
716
	return true;
717
}
718

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

    
723
	$revisions = get_config_backup_count();
724

    
725
	if (!$lock)
726
		$lockkey = lock('config');
727

    
728
	conf_mount_rw();
729

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

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

    
793
	if (!$lock)
794
		unlock($lockkey);
795
}
796

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

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

    
817
	if($g['platform'] == "cdrom")
818
		return;
819

    
820
	conf_mount_rw();
821

    
822
	/* Create backup directory if needed */
823
	safe_mkdir("{$g['cf_conf_path']}/backup");
824

    
825
    if($config['revision']['time'] == "") {
826
            $baktime = 0;
827
    } else {
828
            $baktime = $config['revision']['time'];
829
    }
830
    if($config['revision']['description'] == "") {
831
            $bakdesc = "Unknown";
832
    } else {
833
            $bakdesc = $config['revision']['description'];
834
    }
835

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

    
849
	conf_mount_ro();
850

    
851
	return true;
852
}
853

    
854
function set_device_perms() {
855
	$devices = array(
856
		'pf'	=> array(	'user'	=> 'root',
857
					'group'	=> 'proxy',
858
					'mode'	=> 0660),
859
		);
860

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

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

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

    
882
	return $username;
883
}
884

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

    
891
	$revision = array();
892

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

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

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

    
916
function pfSense_clear_globals() {
917
	global $config, $FilterIfList, $GatewaysList, $filterdns, $aliases, $aliastable;
918

    
919
	if (isset($FilterIfList))
920
		unset($FilterIfList);
921

    
922
	if (isset($GatewaysList))
923
		unset($GatewaysList);
924

    
925
	/* Used for the hostname dns resolver */
926
	if (isset($filterdns))
927
		unset($filterdns);
928

    
929
	/* Used for aliases and interface macros */
930
	if (isset($aliases))
931
		unset($aliases);
932
	if (isset($aliastable))
933
		unset($aliastable);
934

    
935
	unset($config);
936
}
937

    
938
register_shutdown_function('pfSense_clear_globals');
939

    
940
?>
(13-13/68)