<?php # Copyright(C) 2004-2007 INL # Written by Eric Leblond <regit@inl.fr> # Vincent Deffontaines <gryzor@inl.fr> # Jean Gillaux <jean@inl.fr> # Damien Boucard <damien.boucard AT inl.fr> # # $Id: ruleset.class.php 17927 2009-02-16 13:16:09Z haypo $ # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. require_once('desc.class.php'); require_once('elt.class.php'); require_once('obj_set.class.php'); require_once('misc.class.php'); // depends on protocol class require_once('groups.php'); // group class require_once('time.class.php'); require_once('local.class.php'); require_once('acl.class.php'); require_once('order.class.php'); require_once('nat.class.php'); require_once('check.php'); require_once('html.php'); require_once('action_menu.php'); #Do not change this unless you know what you are doing! $xml_nuface_version_old="1.0"; $xml_nuface_version="2.0"; $NUFW_ATTRIBUTES = Array('auths', 'durations', 'applications', 'oss', 'protocols'); class policy extends elt { var $resources; var $auths; var $periodicities; var $durations; var $applications; var $oss; var $protocols; var $l7rules; var $acls; var $localsin; var $localsout; var $snats; var $dnats; var $pnats; var $groups; var $descs; /* creator from xml file */ function policy($filename, $verbose=true, $ruleset_name=null) { global $xml_nuface_version, $xml_nuface_version_old; $this->verbose = $verbose; $this->filename = $filename; if (!$ruleset_name) $ruleset_name = $filename; $this->name = filenameWithoutXml(basename($ruleset_name)); /* parse xml file */ if (!file_exists($this->filename)) throw new Exception(sprintf(_('No such file: "%s".'), $this->filename)); $dom = @domxml_open_file($this->filename); if ($dom) $root = $dom->document_element(); else $root = false; if (!$root) throw new Exception(_('XML syntax error.')); if ($root->tagname() != 'policy') { throw new Exception(_('This XML document in a not a NuFace ruleset!')); } /* check version */ $version = $root->get_attribute('version'); if ($version == $xml_nuface_version_old || $version == '') throw new Exception(_('This ruleset targets NuFace 1.2, pleasy upgrade the ruleset manually.')); if ($version != $xml_nuface_version) throw new Exception(sprintf(_('Unknown NuFace XML format version: %s'), $version)); /* load items */ $this->descs = $this->read_hash($root, 'desc', 'descs', 'desc', false); $this->periodicities = $this->read_hash($root, 'periodicity', "periodicities", "periodicity"); $this->durations = $this->read_hash($root, 'duration', "durations", "duration"); $this->resources = $this->read_hash($root, 'resource', "resources", "resource"); $this->auths = $this->read_hash($root, 'resource', "auths", "auth"); $this->applications = $this->read_hash($root, 'application', "applications", "application"); $this->oss = $this->read_hash($root, 'os', "oss", "os"); $this->protocols = $this->read_hash($root, 'protocol', "protocols", "protocol"); $this->l7rules = $this->read_hash($root, 'l7rule', "l7rules", "l7rule"); $this->groups = $this->read_hash($root, 'group', "groups", "group"); $this->localsin = $this->read_hash($root, 'local', "localsin", "localin"); $this->localsout = $this->read_hash($root, 'local', "localsout", "localout"); $this->acls = $this->read_hash($root, 'acl', "acls", "acl"); $this->snats = $this->read_hash($root, 'nat', "snats", "snat"); $this->dnats = $this->read_hash($root, 'nat', "dnats", "dnat"); $this->pnats = $this->read_hash($root, 'nat', "pnats", "pnat"); $errmsg = $this->check_consistency(null); if ($errmsg) { $errmsg = sprintf(_("%s consistency error: %s!"), $this->str(), $errmsg); throw new Exception($errmsg); } } function str() { return sprintf(_('Ruleset "%s"'), $this->name); } function read_hash($root, $class, $parent_tag_name, $tag_name, $check_dup_names=true) { try { $hash = Array(); $parent = $root->get_elements_by_tagname($parent_tag_name); if ($parent) { $parent = $parent[0]; $children = $parent->get_elements_by_tagname($tag_name); if ($children) { foreach ($children as $item) { $id = $item->get_attribute("ID"); if ($class == 'local') { if ($tag_name == 'localin') $way = 'in'; else $way = 'out'; $value = new $class($this, $way, $item); } else if ($class == 'acl') { $value = new $class($this, $item); } else if ($class == 'nat') { $value = new $class(strtoupper($tag_name), $item); } else { $value = new $class($item); } if (array_key_exists($id, $hash)) { throw new Exception(sprintf(_('Duplicate identifier (%s) for <%s>'), $id, $tag_name)); } $hash[$id] = $value; } } } else if ($parent_tag_name != 'descs') { $this->warning(sprintf(_('Missing XML tag: <%s>.'), $parent_tag_name)); } return new obj_set($parent_tag_name, $hash, $check_dup_names); } catch (Exception $err) { throw new Exception(sprintf( _("Error when reading <%s> XML tag: %s"), $parent_tag_name, $err->getMessage())); } } function warning($message) { if (!$this->verbose) return; add_log(sprintf(_("Warning in %s: %s"), $this->str(), $message)); } function xmldump($filename=''){ global $xml_nuface_version; global $l7_mask; # create new xml document $xml = domxml_new_doc( '1.0' ); $root = $xml->create_element('policy'); $root->set_attribute('version',"$xml_nuface_version"); $new_root = $xml->append_child($root); #descs $node = $xml->create_element( 'descs' ); $newnode = $new_root->append_child($node); $this->descs->xmldump($xml,$newnode); #periodicities $node = $xml->create_element( 'periodicities' ); $newnode = $new_root->append_child($node); $this->periodicities->xmldump($xml,$newnode); #durations $node = $xml->create_element( 'durations' ); $newnode = $new_root->append_child($node); $this->durations->xmldump($xml,$newnode); #resources $node = $xml->create_element( 'resources' ); $newnode = $new_root->append_child($node); $this->resources->xmldump($xml,$newnode); #auths $node = $xml->create_element( 'auths' ); $newnode = $new_root->append_child($node); $this->auths->xmldump($xml,$newnode); #applications $node = $xml->create_element( 'applications' ); $newnode = $new_root->append_child($node); $this->applications->xmldump($xml,$newnode); #oss $node = $xml->create_element( 'oss' ); $newnode = $new_root->append_child($node); $this->oss->xmldump($xml,$newnode); #protocols $node = $xml->create_element( 'protocols' ); $newnode = $new_root->append_child($node); $this->protocols->xmldump($xml,$newnode); #L7rules $node = $xml->create_element( 'l7rules' ); $newnode = $new_root->append_child($node); if (isset($l7_mask) and ($l7_mask!="")) { $node->set_attribute('mask',$l7_mask); } $this->l7rules->xmldump($xml,$newnode); #localsin $node = $xml->create_element( 'localsin' ); $newnode = $new_root->append_child($node); $this->localsin->xmldump($xml,$newnode); #localsout $node = $xml->create_element( 'localsout' ); $newnode = $new_root->append_child($node); $this->localsout->xmldump($xml,$newnode); #acls $node = $xml->create_element( 'acls' ); $newnode = $new_root->append_child($node); $this->acls->xmldump($xml,$newnode); #snats $node = $xml->create_element( 'snats' ); $newnode = $new_root->append_child($node); $this->snats->xmldump($xml,$newnode); #dnats $node = $xml->create_element( 'dnats' ); $newnode = $new_root->append_child($node); $this->dnats->xmldump($xml,$newnode); #pnats $node = $xml->create_element( 'pnats' ); $newnode = $new_root->append_child($node); $this->pnats->xmldump($xml,$newnode); #groups $node = $xml->create_element( 'groups' ); $newnode = $new_root->append_child($node); $this->groups->xmldump($xml,$newnode); # dump xml document if ($filename=='') { echo $xml->dump_mem( true, 'UTF-8' ) ; return true; }else{ return $xml->dump_file($filename,false,true); } } function check_consistency($desc) { if (!check_objects_completeness($this, $desc, $this->auths, 1)) ## 2 means we are on a resources context { return _("Authentication consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->resources, 2)) ## 2 means we are on a resources context { return _("Resource consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->protocols, 3)) ## 3 means we are on a protocols context { return _("Protocol consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->l7rules, 4)) ## 4 means l7 { return _("Layer 7 rule consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->applications, 5)) ## 5 means applications { return _("Application consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->periodicities, 6)) ## 6 means periodicities { return _("Periodicity consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->oss, 7)) ## 7 means os { return _("Operating system consistency problems were found"); } if (!check_objects_completeness($this, $desc, $this->durations, 8)) ## 8 means durations { return _("Duration consistency problems were found"); } return null; } function statistics() { global $nufw_firewall, $l7_firewall, $NUFW_ATTRIBUTES; $ruleset_attributes = Array( # (attribute name, page url without ".php", label) Array('descs', null, _('Networks definition')), Array('resources', 'resources', _('Network resources')), Array('protocols', 'protocols', _('Network protocols')), Array('empty','',''), Array('acls', 'acls', _('FORWARD rules')), Array('localsin', 'localsin', _('INPUT rules')), Array('localsout', 'localsout', _('OUTPUT rules')), Array('empty','',''), Array('snats', 'nat', _('SNAT rules')), Array('dnats', 'nat', _('DNAT rules')), Array('pnats', 'nat', _('PNAT rules')), Array('empty','',''), Array('periodicities', 'periodicities', _('Time periodicities')), Array('durations', 'durations', _('Durations')), Array('empty','',''), Array('auths', 'auths', _('NuFW authentications')), Array('empty','',''), Array('applications', 'applications', _('Applications')), Array('oss', 'os', _('Operating systems')), Array('empty','',''), Array('l7rules', 'l7rules', _('Layer7 rules')), ); $empty = true; # variable used to keep track if we already show a empty line before ( to avoid $show_empty = false; foreach ($ruleset_attributes as $info) { list($attrname, $url, $name) = $info; if (!$nufw_firewall and in_array($attrname, $NUFW_ATTRIBUTES)) { continue; } if (!$l7_firewall and $attrname == 'l7rules') { continue; } if ($attrname == 'empty') { if ( $show_empty) { echo "<tr><td colspan='2'> </td></tr>\n"; $show_empty = false; } continue; } $objset = $this->$attrname; $count = count($objset->elts); if ($count) { if ($url) { $name = createLink($url.'.php', $name); } if ($empty) { echo '<table>'; echo '<tr><th>'._('Type').'</th><th>'._('Count').'</th></tr>'; } $empty = false; echo "<tr><td>$name</td><td>$count</td></tr>"; $show_empty = true; } } if ($empty) { add_log(_("Empty ruleset")); } else { echo "</table>"; } } } # Get chains names from policy function get_chains($policy, $used_desc){ # put artifical chains $res = array(); $descs = $policy->descs; $desc = $descs->elts[$used_desc]; $networks = $desc->networks; foreach($networks->elts as $key=>$network){ $data = $network->datas; $res[] = $data['name']; } return $res; } function read_ruleset_file($filename){ global $datadir; if (!check_filename($filename)) { add_log(sprintf(_('Invalid filename: "%s".'), $filename)); return null; } $filename = $datadir.'/'.$filename; try { $policy = new policy($filename); } catch (Exception $err) { $msg = sprintf(_("Unable to load ruleset file %s: %s"), $filename, $err->getMessage()); log_error($msg, $err->getTrace()); return null; } return $policy; } function write_ruleset_file($ruleset, $filename, $check=true, $reset_modified=true) { global $datadir; $used_desc = getSession('used_desc', false); $descs=$ruleset->descs; recompute_all_descsorts($ruleset, $descs->elts[$used_desc]); if ($check) { $used_desc = getSession('used_desc', false); $desc = $ruleset->descs->elts[$used_desc]; $errmsg = $ruleset->check_consistency($desc); if ($errmsg) { log_error(sprintf(_("Unable to save file because of a consistency error: %s!"), $errmsg)); return false; } } if ($filename==''){ $result = $ruleset->xmldump(); } else { if (!check_filename($filename)) { add_log(sprintf(_('Bad filename: "%s".'), $filename)); return false; } $result = $ruleset->xmldump($datadir.'/'.$filename); // Save success? if ($result) { $name = filenameWithoutXml($filename); add_log(sprintf(_( 'The ruleset "%s" was successfully saved.'), $name)); if ($reset_modified) { $_SESSION['modified'] = 0; } } else { log_error(sprintf( _('An error occured when saving the ruleset to the file "%s"!'), $filename)); } } return $result; } function sessionSaveRuleset($ruleset) { $_SESSION['document'] = serialize($ruleset); } function saveRuleset(&$ruleset) { global $title; sessionSaveRuleset($ruleset); $_SESSION['modified'] = 1; if ($title == 'applications' or $title == 'durations' or $title == 'periodicities' or $title == 'resources' or $title == 'os') { $_SESSION['need_acl_recalc'] = 1; } } function reloadRuleset() { $_SESSION['modified'] = 0; $_SESSION['need_acl_recalc'] = 0; $ruleset = getSession('document'); return $ruleset; } function initRuleset() { $ruleset = getSession('document'); if ($ruleset){ $GLOBALS['expolicy'] = $ruleset; return $ruleset; } // Error: no ruleset is loaded echo sprintf('<span class="error">%s</span>', _("Before you can use NuFace, you have to open a rules file:")); displayNewFirewallButton(); display_openfile_menu(); require_once ("include/footer.php"); exit(1); } ?>