From 8ff5ffccf2d5e0dcdeddbe6ae67a09da4e8458b2 Mon Sep 17 00:00:00 2001 From: Matthew Grooms Date: Thu, 28 Aug 2008 02:53:06 +0000 Subject: [PATCH] Add support for export and import of encrypted configuration files. A set of command line utilities for encypting and decrypting the files format is available from the tools/config-crypto directory. --- etc/inc/crypt.inc | 102 ++++++++++ etc/inc/functions.inc | 1 + usr/local/www/diag_backup.php | 348 +++++++++++++++++++++++----------- 3 files changed, 339 insertions(+), 112 deletions(-) create mode 100644 etc/inc/crypt.inc diff --git a/etc/inc/crypt.inc b/etc/inc/crypt.inc new file mode 100644 index 0000000000..b9bbddd0d9 --- /dev/null +++ b/etc/inc/crypt.inc @@ -0,0 +1,102 @@ + array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("pipe", "e")); + + $fp = proc_open($pspec, $dspec, $pipes); + if (!$fp) + return false; + + fwrite($pipes[0], $data); + fclose($pipes[0]); + + $rslt = stream_get_contents($pipes[1]); + fclose($pipes[1]); + + proc_close($fp); + + return $rslt; + } + + function encrypt_data(& $data, $pass) { + return base64_encode(crypt_data($data, $pass, "-e")); + } + + function decrypt_data(& $data, $pass) { + return crypt_data(base64_decode($data), $pass, "-d"); + } + + function tagfile_reformat($in, & $out, $tag) { + + $out = "---- BEGIN {$tag} ----\n"; + + $size = 80; + $oset = 0; + while ($size >= 64) { + $line = substr($in, $oset, 64); + $out .= $line."\n"; + $size = strlen($line); + $oset += $size; + } + + $out .= "---- END {$tag} ----\n"; + + return true; + } + + function tagfile_deformat($in, & $out, $tag) { + + $btag_val = "---- BEGIN {$tag} ----"; + $etag_val = "---- END {$tag} ----"; + + $btag_len = strlen($btag_val); + $etag_len = strlen($etag_val); + + $btag_pos = stripos($in, $btag_val); + $etag_pos = stripos($in, $etag_val); + + if (($btag_pos === false) || ($etag_pos === false)) + return false; + + $body_pos = $btag_pos + $btag_len; + $body_len = strlen($in); + $body_len -= strlen($btag_len); + $body_len -= strlen($etag_len); + + $out = substr($in, $body_pos, $body_len); + + return true; + } +?> diff --git a/etc/inc/functions.inc b/etc/inc/functions.inc index c5c7ccab01..f35e960316 100644 --- a/etc/inc/functions.inc +++ b/etc/inc/functions.inc @@ -73,6 +73,7 @@ if(!function_exists("pfSenseHeader")) { require_once("auth.inc"); require_once("priv.inc"); require_once("certs.inc"); +require_once("crypt.inc"); require_once("captiveportal.inc"); require_once("filter.inc"); require_once("interfaces.inc"); diff --git a/usr/local/www/diag_backup.php b/usr/local/www/diag_backup.php index 2ddf48f2bf..29d54741c2 100755 --- a/usr/local/www/diag_backup.php +++ b/usr/local/www/diag_backup.php @@ -92,125 +92,156 @@ if ($_POST) { $ver2restore = $_POST["ver"]; if ($mode) { + if ($mode == "download") { - config_lock(); - $fn = "config-" . $config['system']['hostname'] . "." . - $config['system']['domain'] . "-" . date("YmdHis") . ".xml"; - if($options == "nopackages") { - exec("sed '//,/<\/installedpackages>/d' /conf/config.xml > /tmp/config.xml.nopkg"); - $fs = filesize("{$g['tmp_path']}/config.xml.nopkg"); - header("Content-Type: application/octet-stream"); - header("Content-Disposition: attachment; filename=$fn"); - header("Content-Length: $fs"); - readfile("{$g['tmp_path']}/config.xml.nopkg"); - } else { - if($_POST['backuparea'] <> "") { - /* user wishes to backup specific area of configuration */ - $current_trafficshaper_section = backup_config_section($_POST['backuparea']); - /* generate aliases xml */ - $fout = fopen("{$g['tmp_path']}/backup_section.txt","w"); - fwrite($fout, $current_trafficshaper_section); - fclose($fout); - $fs = filesize($g['tmp_path'] . "/backup_section.txt"); - header("Content-Type: application/octet-stream"); - $fn = $_POST['backuparea'] . "-" . $fn; - header("Content-Disposition: attachment; filename=$fn"); - header("Content-Length: $fs"); - readfile($g['tmp_path'] . "/backup_section.txt"); - unlink($g['tmp_path'] . "/backup_section.txt"); - } else { - $fs = filesize($g['conf_path'] . "/config.xml"); - header("Content-Type: application/octet-stream"); - header("Content-Disposition: attachment; filename=$fn"); - header("Content-Length: $fs"); - readfile($g['conf_path'] . "/config.xml"); - } + + if ($_POST['encrypt']) { + if(!$_POST['encrypt_password'] || !$_POST['encrypt_passconf']) + $input_errors[] = "You must supply and confirm the password for encryption."; + if($_POST['encrypt_password'] != $_POST['encrypt_passconf']) + $input_errors[] = "The supplied 'Password' and 'Confirm' field values must match."; } - config_unlock(); - exit; - } else if ($mode == "restore") { - if (is_uploaded_file($_FILES['conffile']['tmp_name'])) { - $fd = fopen($_FILES['conffile']['tmp_name'], "r"); - if(!$fd) { - log_error("Warning, could not open " . $_FILES['conffile']['tmp_name']); - return 1; - } - while(!feof($fd)) { - $tmp .= fread($fd,49); - } - fclose($fd); - if(stristr($tmp, "m0n0wall") == true) { - log_error("Upgrading m0n0wall configuration to pfsense."); - /* m0n0wall was found in config. convert it. */ - $upgradedconfig = str_replace("m0n0wall", "pfsense", $tmp); - $fd = fopen($_FILES['conffile']['tmp_name'], "w"); - fwrite($fd, $upgradedconfig); - fclose($fd); - $m0n0wall_upgrade = true; - } - if($_POST['restorearea'] <> "") { - /* restore a specific area of the configuration */ - $rules = file_get_contents($_FILES['conffile']['tmp_name']); - if(stristr($rules, $_POST['restorearea']) == false) { - $input_errors[] = "You have selected to restore a area but we could not locate the correct xml tag."; - } else { - restore_config_section($_POST['restorearea'], $rules); - filter_configure(); - $savemsg = "The configuration area has been restored. You may need to reboot the firewall."; - } + + if (!$input_errors) { + + config_lock(); + + $host = "{$config['system']['hostname']}.{$config['system']['domain']}"; + $name = "config-{$host}-".date("YmdHis").".xml"; + $data = ""; + + if($options == "nopackages") { + $sfn = "/tmp/config.xml.nopkg"; + exec("sed '//,/<\/installedpackages>/d' /conf/config.xml > {$sfn}"); + $data = file_get_contents($sfn); } else { - $rules = file_get_contents($_FILES['conffile']['tmp_name']); - if(stristr($rules, "pfsense") == false) { - $input_errors[] = "You have selected to restore the full configuration but we could not locate a pfsense tag."; + if(!$_POST['backuparea']) { + /* backup entire configuration */ + $data = file_get_contents("{$g['conf_path']}/config.xml"); } else { - /* restore the entire configuration */ - if (config_install($_FILES['conffile']['tmp_name']) == 0) { - /* this will be picked up by /index.php */ - conf_mount_rw(); - if($g['platform'] <> "cdrom") - touch("/needs_package_sync"); - $reboot_needed = true; - $savemsg = "The configuration has been restored. The firewall is now rebooting."; - /* remove cache, we will force a config reboot */ - if(file_exists("/tmp/config.cache")) - unlink("/tmp/config.cache"); - $config = parse_config(true); - if($m0n0wall_upgrade == true) { - if($config['system']['gateway'] <> "") - $config['interfaces']['wan']['gateway'] = $config['system']['gateway']; - unset($config['shaper']); - /* optional if list */ - $ifdescrs = get_configured_interface_list(true, true); - /* remove special characters from interface descriptions */ - if(is_array($ifdescrs)) - foreach($ifdescrs as $iface) - $config['interfaces'][$iface]['descr'] = remove_bad_chars($config['interfaces'][$iface]['descr']); - unlink_if_exists("/tmp/config.cache"); - write_config(); - conf_mount_ro(); - $savemsg = "The m0n0wall configuration has been restored and upgraded to pfSense.

The firewall is now rebooting."; - $reboot_needed = true; - } - if(isset($config['captiveportal']['enable'])) { - /* for some reason ipfw doesn't init correctly except on bootup sequence */ - $savemsg = "The configuration has been restored.

The firewall is now rebooting."; - $reboot_needed = true; - } - setup_serial_port(); - if(is_interface_mismatch() == true) { - touch("/var/run/interface_mismatch_reboot_needed"); - $reboot_needed = false; - header("Location: interfaces_assign.php"); - } + /* backup specific area of configuration */ + $data = backup_config_section($_POST['backuparea']); + $name = "{$_POST['backuparea']}-{$name}"; + } + } + + if ($_POST['encrypt']) { + $data = encrypt_data($data, $_POST['encrypt_password']); + tagfile_reformat($data, $data, "config.xml"); + } + + $size = strlen($data); + header("Content-Type: application/octet-stream"); + header("Content-Disposition: attachment; filename={$name}"); + header("Content-Length: $size"); + echo $data; + + config_unlock(); + exit; + } + } + + if ($mode == "restore") { + + if ($_POST['decrypt']) { + if(!$_POST['decrypt_password'] || !$_POST['decrypt_passconf']) + $input_errors[] = "You must supply and confirm the password for decryption."; + if($_POST['decrypt_password'] != $_POST['decrypt_passconf']) + $input_errors[] = "The supplied 'Password' and 'Confirm' field values must match."; + } + + if (!$input_errors) { + + if (is_uploaded_file($_FILES['conffile']['tmp_name'])) { + + /* read the file contents */ + $data = file_get_contents($_FILES['conffile']['tmp_name']); + if(!$data) { + log_error("Warning, could not read file " . $_FILES['conffile']['tmp_name']); + return 1; + } + + if ($_POST['decrypt']) { + if (!tagfile_deformat($data, $data, "config.xml")) { + $input_errors[] = "The uploaded file does not appear to contain an encrypted pfsense configuration."; + return 1; + } + $data = decrypt_data($data, $_POST['decrypt_password']); + } + + if(stristr($data, "m0n0wall")) { + log_error("Upgrading m0n0wall configuration to pfsense."); + /* m0n0wall was found in config. convert it. */ + $data = str_replace("m0n0wall", "pfsense", $data); + $m0n0wall_upgrade = true; + } + + if($_POST['restorearea']) { + /* restore a specific area of the configuration */ + if(!stristr($data, $_POST['restorearea'])) { + $input_errors[] = "You have selected to restore a area but we could not locate the correct xml tag."; } else { - $input_errors[] = "The configuration could not be restored."; + restore_config_section($_POST['restorearea'], $data); + filter_configure(); + $savemsg = "The configuration area has been restored. You may need to reboot the firewall."; + } + } else { + if(!stristr($data, "")) { + $input_errors[] = "You have selected to restore the full configuration but we could not locate a pfsense tag."; + } else { + /* restore the entire configuration */ + file_put_contents($_FILES['conffile']['tmp_name'], $data); + if (config_install($_FILES['conffile']['tmp_name']) == 0) { + /* this will be picked up by /index.php */ + conf_mount_rw(); + if($g['platform'] <> "cdrom") + touch("/needs_package_sync"); + $reboot_needed = true; + $savemsg = "The configuration has been restored. The firewall is now rebooting."; + /* remove cache, we will force a config reboot */ + if(file_exists("/tmp/config.cache")) + unlink("/tmp/config.cache"); + $config = parse_config(true); + if($m0n0wall_upgrade == true) { + if($config['system']['gateway'] <> "") + $config['interfaces']['wan']['gateway'] = $config['system']['gateway']; + unset($config['shaper']); + /* optional if list */ + $ifdescrs = get_configured_interface_list(true, true); + /* remove special characters from interface descriptions */ + if(is_array($ifdescrs)) + foreach($ifdescrs as $iface) + $config['interfaces'][$iface]['descr'] = remove_bad_chars($config['interfaces'][$iface]['descr']); + unlink_if_exists("/tmp/config.cache"); + write_config(); + conf_mount_ro(); + $savemsg = "The m0n0wall configuration has been restored and upgraded to pfSense.

The firewall is now rebooting."; + $reboot_needed = true; + } + if(isset($config['captiveportal']['enable'])) { + /* for some reason ipfw doesn't init correctly except on bootup sequence */ + $savemsg = "The configuration has been restored.

The firewall is now rebooting."; + $reboot_needed = true; + } + setup_serial_port(); + if(is_interface_mismatch() == true) { + touch("/var/run/interface_mismatch_reboot_needed"); + $reboot_needed = false; + header("Location: interfaces_assign.php"); + } + } else { + $input_errors[] = "The configuration could not be restored."; + } } } + } else { + $input_errors[] = "The configuration could not be restored (file upload error)."; } - } else { - $input_errors[] = "The configuration could not be restored (file upload error)."; } - } else if ($mode == "reinstallpackages") { + } + + if ($mode == "reinstallpackages") { + header("Location: pkg_mgr_install.php?mode=reinstallall"); exit; } else if ($mode == "restore_ver") { @@ -242,7 +273,28 @@ include("head.inc"); -

+ + @@ -267,7 +319,44 @@ include("head.inc"); @@ -282,6 +371,34 @@ include("head.inc"); @@ -308,6 +425,13 @@ include("head.inc");
 

Click this button to download the system configuration in XML format.

Backup area:

-

Do not backup package information.

+ + + + + +
+ + + Do not backup package information. +
+ + + + + +
+ + + Encrypt this configuration file. +
+ + + + + + + + + +
+ Password : + + +
+ confirm : + + +

Open a configuration XML file and click the button below to restore the configuration.

Restore area:

+ + + + + +
+ + + Configuration file is encrypted. +
+ + + + + + + + + +
+ Password : + + +
+ confirm : + + +

Note:
The firewall may need a reboot after restoring the configuration.

+ +