. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /****f* config/encrypted_configxml * NAME * encrypted_configxml - Checks to see if config.xml is encrypted and if so, prompts to unlock. * INPUTS * None * RESULT * $config - rewrites config.xml without encryption ******/ function encrypted_configxml() { global $g, $config; if (!file_exists($g['conf_path'] . "/config.xml")) { return; } if (!platform_booting()) { return; } $configtxt = file_get_contents($g['conf_path'] . "/config.xml"); if (tagfile_deformat($configtxt, $configtxt, "config.xml")) { $fp = fopen('php://stdin', 'r'); $data = ""; echo "\n\n*** Encrypted config.xml detected ***\n"; while ($data == "") { echo "\nEnter the password to decrypt config.xml: "; $decrypt_password = chop(fgets($fp)); $data = decrypt_data($configtxt, $decrypt_password); if (!strstr($data, "")) { $data = ""; } if ($data) { $fd = fopen($g['conf_path'] . "/config.xml.tmp", "w"); fwrite($fd, $data); fclose($fd); exec("/bin/mv {$g['conf_path']}/config.xml.tmp {$g['conf_path']}/config.xml"); echo "\n" . gettext("Config.xml unlocked.") . "\n"; fclose($fp); pfSense_fsync("{$g['conf_path']}/config.xml"); } else { echo "\n" . gettext("Invalid password entered. Please try again.") . "\n"; } } } } /****f* config/parse_config * NAME * parse_config - Read in config.cache or config.xml if needed and return $config array * INPUTS * $parse - boolean to force parse_config() to read config.xml and generate config.cache * RESULT * $config - array containing all configuration variables ******/ function parse_config($parse = false) { global $g, $config_parsed, $config_extra; $lockkey = lock('config'); $config_parsed = false; if (!file_exists("{$g['conf_path']}/config.xml") || filesize("{$g['conf_path']}/config.xml") == 0) { $last_backup = discover_last_backup(); if ($last_backup) { log_error(gettext("No config.xml found, attempting last known config restore.")); file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", ""); restore_backup("{$g['conf_path']}/backup/{$last_backup}"); } else { unlock($lockkey); die(gettext("Config.xml is corrupted and is 0 bytes. Could not restore a previous backup.")); } } if (platform_booting(true)) { echo "."; } // Check for encrypted config.xml encrypted_configxml(); if (!$parse) { if (file_exists($g['tmp_path'] . '/config.cache')) { $config = unserialize(file_get_contents($g['tmp_path'] . '/config.cache')); if (!is_array($config)) { $parse = true; } } else { $parse = true; } } if ($parse == true) { if (!file_exists($g['conf_path'] . "/config.xml")) { if (platform_booting(true)) { echo "."; } log_error("No config.xml found, attempting last known config restore."); file_notice("config.xml", "No config.xml found, attempting last known config restore.", "pfSenseConfigurator", ""); $last_backup = discover_last_backup(); if ($last_backup) { restore_backup("/cf/conf/backup/{$last_backup}"); } else { log_error(gettext("Could not restore config.xml.")); unlock($lockkey); die(gettext("Config.xml is corrupted and is 0 bytes. Could not restore a previous backup.")); } } $config = parse_xml_config($g['conf_path'] . '/config.xml', array($g['xml_rootobj'], 'pfsense')); if ($config == -1) { $last_backup = discover_last_backup(); if ($last_backup) { restore_backup("/cf/conf/backup/{$last_backup}"); } else { log_error(gettext("Could not restore config.xml.")); unlock($lockkey); die("Config.xml is corrupted and is 0 bytes. Could not restore a previous backup."); } } generate_config_cache($config); } if (platform_booting(true)) { echo "."; } $config_parsed = true; unlock($lockkey); alias_make_table($config); return $config; } /****f* config/generate_config_cache * NAME * generate_config_cache - Write serialized configuration to cache. * INPUTS * $config - array containing current firewall configuration * RESULT * boolean - true on completion ******/ function generate_config_cache($config) { global $g, $config_extra; $configcache = fopen($g['tmp_path'] . '/config.cache', "w"); fwrite($configcache, serialize($config)); fclose($configcache); pfSense_fsync("{$g['tmp_path']}/config.cache"); unset($configcache); /* Used for config.extra.xml */ if (file_exists($g['tmp_path'] . '/config.extra.cache') && $config_extra) { $configcacheextra = fopen($g['tmp_path'] . '/config.extra.cache', "w"); fwrite($configcacheextra, serialize($config_extra)); fclose($configcacheextra); pfSense_fsync("{$g['tmp_path']}/config.extra.cache"); unset($configcacheextra); } } function discover_last_backup() { $backups = glob('/cf/conf/backup/*.xml'); $last_backup = ""; $last_mtime = 0; foreach ($backups as $backup) { if (filemtime($backup) > $last_mtime) { $last_mtime = filemtime($backup); $last_backup = $backup; } } return basename($last_backup); } function restore_backup($file) { global $g; if (file_exists($file)) { unlink_if_exists("{$g['tmp_path']}/config.cache"); copy("$file", "/cf/conf/config.xml"); pfSense_fsync("/cf/conf/config.xml"); pfSense_fsync($g['conf_path']); disable_security_checks(); log_error(sprintf(gettext('%1$s is restoring the configuration %2$s'), $g['product_name'], $file)); file_notice("config.xml", sprintf(gettext('%1$s is restoring the configuration %2$s'), $g['product_name'], $file), "pfSenseConfigurator", ""); } } /****f* config/parse_config_bootup * NAME * parse_config_bootup - Bootup-specific configuration checks. * RESULT * null ******/ function parse_config_bootup() { global $config, $g; if (platform_booting()) { echo "."; } $lockkey = lock('config'); if (!file_exists("{$g['conf_path']}/config.xml")) { if (platform_booting()) { $last_backup = discover_last_backup(); if ($last_backup) { log_error("No config.xml found, attempting last known config restore."); file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", ""); restore_backup("/cf/conf/backup/{$last_backup}"); } if (!file_exists("{$g['conf_path']}/config.xml")) { echo sprintf(gettext("XML configuration file not found. %s cannot continue booting."), $g['product_name']) . "\n"; unlock($lockkey); mwexec("/sbin/halt"); exit; } log_error("Last known config found and restored. Please double check the configuration file for accuracy."); file_notice("config.xml", gettext("Last known config found and restored. Please double check the configuration file for accuracy."), "pfSenseConfigurator", ""); } else { unlock($lockkey); log_error(gettext("Could not find a usable configuration file! Exiting....")); exit(0); } } if (filesize("{$g['conf_path']}/config.xml") == 0) { $last_backup = discover_last_backup(); if ($last_backup) { log_error(gettext("No config.xml found, attempting last known config restore.")); file_notice("config.xml", gettext("No config.xml found, attempting last known config restore."), "pfSenseConfigurator", ""); restore_backup("{$g['conf_path']}/backup/{$last_backup}"); } else { unlock($lockkey); die(gettext("Config.xml is corrupted and is 0 bytes. Could not restore a previous backup.")); } } unlock($lockkey); $config = parse_config(true); if ((float)$config['version'] > (float)$g['latest_config']) { echo << $newxml['revision']['description'], 'version' => $newxml['version'], 'filesize' => $backupsize); } } foreach ($backups as $checkbak) { if (count(preg_grep('/' . $checkbak['time'] . '/i', $bakfiles)) != 0) { $newbaks[] = $checkbak; } else { $i = true; if (platform_booting()) print " " . $tocheck . "r"; } } foreach ($newbaks as $todo) { $tocache[$todo['time']] = array('description' => $todo['description'], 'version' => $todo['version'], 'filesize' => $todo['filesize']); } if (is_int($revisions) and (count($tocache) > $revisions)) { $toslice = array_slice(array_keys($tocache), 0, $revisions); foreach ($toslice as $sliced) { $newcache[$sliced] = $tocache[$sliced]; } foreach ($tocache as $version => $versioninfo) { if (!in_array($version, array_keys($newcache))) { unlink_if_exists($g['conf_path'] . '/backup/config-' . $version . '.xml'); } } $tocache = $newcache; } $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w"); fwrite($bakout, serialize($tocache)); fclose($bakout); pfSense_fsync("{$g['cf_conf_path']}/backup/backup.cache"); if (!$lock) { unlock($lockkey); } } function get_backups() { global $g; if (file_exists("{$g['cf_conf_path']}/backup/backup.cache")) { $confvers = unserialize(file_get_contents("{$g['cf_conf_path']}/backup/backup.cache")); $bakvers = array_keys($confvers); $toreturn = array(); sort($bakvers); // $bakvers = array_reverse($bakvers); foreach (array_reverse($bakvers) as $bakver) { $toreturn[] = array('time' => $bakver, 'description' => $confvers[$bakver]['description'], 'version' => $confvers[$bakver]['version'], 'filesize' => $confvers[$bakver]['filesize']); } } else { return false; } $toreturn['versions'] = $bakvers; return $toreturn; } function backup_config() { global $config, $g; /* Create backup directory if needed */ safe_mkdir("{$g['cf_conf_path']}/backup"); if ($config['revision']['time'] == "") { $baktime = 0; } else { $baktime = $config['revision']['time']; } if ($config['revision']['description'] == "") { $bakdesc = "Unknown"; } else { $bakdesc = $config['revision']['description']; } $bakver = ($config['version'] == "") ? "?" : $config['version']; $bakfilename = $g['cf_conf_path'] . '/backup/config-' . $baktime . '.xml'; copy($g['cf_conf_path'] . '/config.xml', $bakfilename); if (file_exists($g['cf_conf_path'] . '/backup/backup.cache')) { $backupcache = unserialize(file_get_contents($g['cf_conf_path'] . '/backup/backup.cache')); } else { $backupcache = array(); } $backupcache[$baktime] = array('description' => $bakdesc, 'version' => $bakver, 'filesize' => filesize($bakfilename)); $bakout = fopen($g['cf_conf_path'] . '/backup/backup.cache', "w"); fwrite($bakout, serialize($backupcache)); fclose($bakout); pfSense_fsync("{$g['cf_conf_path']}/backup/backup.cache"); return true; } function set_device_perms() { $devices = array( 'pf' => array( 'user' => 'root', 'group' => 'proxy', 'mode' => 0660), ); foreach ($devices as $name => $attr) { $path = "/dev/$name"; if (file_exists($path)) { chown($path, $attr['user']); chgrp($path, $attr['group']); chmod($path, $attr['mode']); } } } function get_config_user() { if (empty($_SESSION["Username"])) { $username = getenv("USER"); if (empty($conuser) || $conuser == "root") { $username = "(system)"; } } else { $username = $_SESSION["Username"]; } if (!empty($_SERVER['REMOTE_ADDR'])) { $username .= '@' . $_SERVER['REMOTE_ADDR']; } return $username; } function make_config_revision_entry($desc = null, $override_user = null) { if (empty($override_user)) { $username = get_config_user(); } else { $username = $override_user; } $revision = array(); if (time() > mktime(0, 0, 0, 9, 1, 2004)) { /* make sure the clock settings are plausible */ $revision['time'] = time(); } /* Log the running script so it's not entirely unlogged what changed */ if ($desc == "Unknown") { $desc = sprintf(gettext("%s made unknown change"), $_SERVER['SCRIPT_NAME']); } if (!empty($desc)) { $revision['description'] = "{$username}: " . $desc; } $revision['username'] = $username; return $revision; } function pfSense_clear_globals() { global $config, $FilterIfList, $GatewaysList, $filterdns, $aliases, $aliastable; $error = error_get_last(); if ($error !== NULL) { if ($error['type'] == E_ERROR) { $errorstr = "PHP ERROR: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}"; print($errorstr); log_error($errorstr); } else if ($error['type'] != E_NOTICE) { $errorstr = "PHP WARNING: Type: {$error['type']}, File: {$error['file']}, Line: {$error['line']}, Message: {$error['message']}"; // XXX: comment out for now, should re-enable post-2.2 //print($errorstr); //log_error($errorstr); } } if (isset($FilterIfList)) { unset($FilterIfList); } if (isset($GatewaysList)) { unset($GatewaysList); } /* Used for the hostname dns resolver */ if (isset($filterdns)) { unset($filterdns); } /* Used for aliases and interface macros */ if (isset($aliases)) { unset($aliases); } if (isset($aliastable)) { unset($aliastable); } unset($config); } register_shutdown_function('pfSense_clear_globals'); ?>