diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d07c6384..58600a26 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,11 +1,14 @@ CHANGELOG -2.0.31 +2.0.31 (20220303) UTILS: * pan-os-php type=xml-issue | extend fix for custom-url-category * UTIL type=application | introduce new 'filters=( decoder has XYZ )' / (decoder is.set) * UTIL type=securityprofile securityprofiletype=custom-url-category | actions=exporttoexcel introduce display of member information * UTIL BETA ssh_connector.php | extend with argument setcommand-maxline=20 +* UTIL type=rule | introduce new 'filter=(service port.counter.greater.than 1000)' / service port.tcp.counter.greater.than 1000 / service port.udp.counter.greater.than +* UTIL type=service | introduce new actions=show-dstportmapping +* UTIL type=address | improvement for actions=showip4mapping to display unresolved objects BUGFIX: * UTIL type=diff | replace derr() with mwarning() - fix for argument outputformatset @@ -13,6 +16,8 @@ BUGFIX: * UTIL type=securityprofile | bugfix missing array variable declaration * UTIL type=rule | bugfix for 'filter=(service has.value.recursive PORT-RANGE)' * UTIL type=rule 'filter=(service has.value.recursive PORT-RANGE)' | bugfix if searched PORT-RANGE is partial available, and if multiple port-range are available in service-group +* UTIL type=rule | bugfix for 'filter=(service has.value.recursive PORT-RANGE)' to match if two different nested groups has combined the filtered PORT-RANGE +* UTIL type=rule | class ServiceDstPortMapping - bugfix to for 'filter=(service port.counter.greater.than 10)' GENERAL: * framework all Object Classes | improve code for usage of single method parentCentralStore() diff --git a/lib/container-classes/ServiceRuleContainer.php b/lib/container-classes/ServiceRuleContainer.php index d9a59995..a6056686 100644 --- a/lib/container-classes/ServiceRuleContainer.php +++ b/lib/container-classes/ServiceRuleContainer.php @@ -612,11 +612,16 @@ function hasValue($value, $check_recursive = FALSE) } $objects = $this->o; - foreach( $objects as $object ) + + foreach( $objects as $key => $object ) { if( !$check_recursive ) if( $object->isGroup() ) + { + unset( $objects[$key] ); continue; + } + if( !$object->isGroup() ) if( $value == $object->getDestPort() ) @@ -625,40 +630,17 @@ function hasValue($value, $check_recursive = FALSE) $port_mapping = $object->dstPortMapping(); $port_mapping_text = $port_mapping->mappingToText(); - if( strpos($port_mapping_text, " ") !== FALSE ) - $port_mapping_array = explode(" ", $port_mapping_text); - else - $port_mapping_array[0] = $port_mapping_text; + if( self::checkPortMapping( $port_mapping_text, $rangeValue, $port_value_range, $value) ) + return TRUE; + } - foreach( $port_mapping_array as $port_mapping_text ) - { - $text_replace = array('tcp/', 'udp/'); - $port_mapping_text = str_replace($text_replace, "", $port_mapping_text); + $dst_port_mapping = new ServiceDstPortMapping(); + $dst_port_mapping->mergeWithArrayOfServiceObjects( $objects); - if( strpos($port_mapping_text, ",") !== FALSE ) - { - $port_mapping_list = explode(",", $port_mapping_text); - foreach( $port_mapping_list as $list_object ) - { - if( $value == $list_object ) - return TRUE; - elseif( strpos($list_object, "-") !== FALSE ) - { - if( self::checkValueRange( $rangeValue, $port_value_range, $value, $list_object) ) - return TRUE; - } - } - } - elseif( strpos($port_mapping_text, "-") !== FALSE ) - { - if( self::checkValueRange( $rangeValue, $port_value_range, $value, $port_mapping_text) ) - return TRUE; - } + $port_mapping_text = $dst_port_mapping->mappingToText(); - elseif( $value == $port_mapping_text ) - return TRUE; - } - } + if( self::checkPortMapping( $port_mapping_text, $rangeValue, $port_value_range, $value) ) + return TRUE; return FALSE; } @@ -677,6 +659,43 @@ public function checkValueRange( $rangeValue, $port_value_range, $value, $port_m return TRUE; } } + + public function checkPortMapping( $port_mapping_text, $rangeValue, $port_value_range, $value) + { + if( strpos($port_mapping_text, " ") !== FALSE ) + $port_mapping_array = explode(" ", $port_mapping_text); + else + $port_mapping_array[0] = $port_mapping_text; + + foreach( $port_mapping_array as $port_mapping_text ) + { + $text_replace = array('tcp/', 'udp/'); + $port_mapping_text = str_replace($text_replace, "", $port_mapping_text); + + if( strpos($port_mapping_text, ",") !== FALSE ) + { + $port_mapping_list = explode(",", $port_mapping_text); + foreach( $port_mapping_list as $list_object ) + { + if( $value == $list_object ) + return TRUE; + elseif( strpos($list_object, "-") !== FALSE ) + { + if( self::checkValueRange( $rangeValue, $port_value_range, $value, $list_object) ) + return TRUE; + } + } + } + elseif( strpos($port_mapping_text, "-") !== FALSE ) + { + if( self::checkValueRange( $rangeValue, $port_value_range, $value, $port_mapping_text) ) + return TRUE; + } + + elseif( $value == $port_mapping_text ) + return TRUE; + } + } } diff --git a/lib/helper-classes/ServiceDstPortMapping.php b/lib/helper-classes/ServiceDstPortMapping.php index 190f1a46..37e15f06 100644 --- a/lib/helper-classes/ServiceDstPortMapping.php +++ b/lib/helper-classes/ServiceDstPortMapping.php @@ -22,6 +22,11 @@ class ServiceDstPortMapping { public $tcpPortMap = array(); public $udpPortMap = array(); + + public $tcpPortCounter = 0; + public $udpPortCounter = 0; + public $PortCounter = 0; + /** @var Service[]|ServiceGroup[] */ public $unresolved = array(); @@ -119,52 +124,38 @@ public function mergeOverlappingMappings() $mapKeys = array_keys($newMapping); $mapCount = count($newMapping); - for( $i = 0; $i < $mapCount; $i++ ) - { - $current = &$newMapping[$mapKeys[$i]]; - //PH::print_stdout( " - handling ".long2ip($current['start'])."-".long2ip($current['end']) ); - for( $j = $i + 1; $j < $mapCount; $j++ ) - { - $compare = &$newMapping[$mapKeys[$j]]; - //PH::print_stdout( " - vs ".long2ip($compare['start'])."-".long2ip($compare['end']) ); + self::calculateMergerOverlapping($newMapping, $mapKeys, $mapCount ); - if( $compare['start'] > $current['end'] + 1 ) - break; - - if( $current['end'] < $compare['end'] ) - $current['end'] = $compare['end']; - - unset($newMapping[$mapKeys[$j]]); - - $i++; - } - } $newMapping = &$this->udpPortMap; $mapKeys = array_keys($newMapping); $mapCount = count($newMapping); + self::calculateMergerOverlapping($newMapping, $mapKeys, $mapCount ); + } + + public function calculateMergerOverlapping(&$newMapping, $mapKeys, $mapCount ) + { for( $i = 0; $i < $mapCount; $i++ ) { $current = &$newMapping[$mapKeys[$i]]; - //PH::print_stdout( " - handling ".long2ip($current['start'])."-".long2ip($current['end']) ); for( $j = $i + 1; $j < $mapCount; $j++ ) { $compare = &$newMapping[$mapKeys[$j]]; - //PH::print_stdout( " - vs ".long2ip($compare['start'])."-".long2ip($compare['end']) ); if( $compare['start'] > $current['end'] + 1 ) break; - $current['end'] = $compare['end']; + if( $current['end'] < $compare['end'] ) + $current['end'] = $compare['end']; unset($newMapping[$mapKeys[$j]]); $i++; } } - } + public function mergeWithMapping(ServiceDstPortMapping $otherMapping) { foreach( $otherMapping->tcpPortMap as $map ) @@ -206,7 +197,7 @@ public function &tcpMappingToText() if( $map['start'] == $map['end'] ) $mapsText[] = "tcp/".(string)$map['start']; else - $mapsText[] = "tcp/".$map['start'] . '-' . $map['end']; + $mapsText[] = "tcp/".(string)$map['start'] . '-' . (string)$map['end']; } $returnText = PH::list_to_string($mapsText, ","); @@ -230,7 +221,7 @@ public function &udpMappingToText( ) if( $map['start'] == $map['end'] ) $mapsText[] = "udp/".(string)$map['start']; else - $mapsText[] = "udp/".$map['start'] . '-' . $map['end']; + $mapsText[] = "udp/".(string)$map['start'] . '-' . (string)$map['end']; } $returnText = PH::list_to_string($mapsText, ","); @@ -329,4 +320,32 @@ public function mappingToText() return $returnText; } + + + public function countPortmapping() + { + foreach( $this->tcpPortMap as &$map ) + { + if( $map['start'] == $map['end'] ) + $this->tcpPortCounter += 1; + else + { + $tmpcount = (int)$map['end'] - (int)$map['start'] +1; + $this->tcpPortCounter += $tmpcount; + } + } + + foreach( $this->udpPortMap as &$map ) + { + if( $map['start'] == $map['end'] ) + $this->udpPortCounter += 1; + else + { + $tmpcount = (int)$map['end'] - (int)$map['start'] +1; + $this->udpPortCounter += $tmpcount; + } + } + + $this->PortCounter = $this->tcpPortCounter + $this->udpPortCounter; + } } diff --git a/lib/misc-classes/filters/filters-Rule.php b/lib/misc-classes/filters/filters-Rule.php index 9134414f..8ce83d9c 100644 --- a/lib/misc-classes/filters/filters-Rule.php +++ b/lib/misc-classes/filters/filters-Rule.php @@ -1615,6 +1615,95 @@ ) ); +RQuery::$defaultFilters['rule']['service']['operators']['port.counter.greater.than'] = array( + 'Function' => function (RuleRQueryContext $context) { + $counter = $context->value; + $rule = $context->object; + + if( $rule->isNatRule() ) + { + mwarning("this filter does not yet support NAT Rules"); + return FALSE; + } + + $objects = $rule->services->o; + + $dst_port_mapping = new ServiceDstPortMapping(); + $dst_port_mapping->mergeWithArrayOfServiceObjects( $objects); + + $dst_port_mapping->countPortmapping(); + + if( $dst_port_mapping->PortCounter > $counter ) + return TRUE; + + return FALSE; + }, + 'arg' => TRUE, + 'ci' => array( + 'fString' => '(%PROP% 443)', + 'input' => 'input/panorama-8.0.xml' + ) +); + +RQuery::$defaultFilters['rule']['service']['operators']['port.tcp.counter.greater.than'] = array( + 'Function' => function (RuleRQueryContext $context) { + $counter = $context->value; + $rule = $context->object; + + if( $rule->isNatRule() ) + { + mwarning("this filter does not yet support NAT Rules"); + return FALSE; + } + + $objects = $rule->services->o; + + $dst_port_mapping = new ServiceDstPortMapping(); + $dst_port_mapping->mergeWithArrayOfServiceObjects( $objects); + + $dst_port_mapping->countPortmapping(); + + if( $dst_port_mapping->tcpPortCounter > $counter ) + return TRUE; + + return FALSE; + }, + 'arg' => TRUE, + 'ci' => array( + 'fString' => '(%PROP% 443)', + 'input' => 'input/panorama-8.0.xml' + ) +); + +RQuery::$defaultFilters['rule']['service']['operators']['port.udp.counter.greater.than'] = array( + 'Function' => function (RuleRQueryContext $context) { + $counter = $context->value; + $rule = $context->object; + + if( $rule->isNatRule() ) + { + mwarning("this filter does not yet support NAT Rules"); + return FALSE; + } + + $objects = $rule->services->o; + + $dst_port_mapping = new ServiceDstPortMapping(); + $dst_port_mapping->mergeWithArrayOfServiceObjects( $objects); + + $dst_port_mapping->countPortmapping(); + + if( $dst_port_mapping->udpPortCounter > $counter ) + return TRUE; + + return FALSE; + }, + 'arg' => TRUE, + 'ci' => array( + 'fString' => '(%PROP% 443)', + 'input' => 'input/panorama-8.0.xml' + ) +); // // // SecurityProfile properties // // // diff --git a/utils/common/actions-address.php b/utils/common/actions-address.php index 613b6328..3b9f592d 100644 --- a/utils/common/actions-address.php +++ b/utils/common/actions-address.php @@ -1579,20 +1579,29 @@ if( $object->isGroup() ) { $resolvMap = $object->getIP4Mapping(); - $string = "* {$resolvMap->count()} entries"; + $string = "{$resolvMap->count()} entries"; PH::ACTIONlog( $context, $string ); + foreach( $resolvMap->getMapArray() as &$resolvRecord ) { //Todo: swaschkut 20210421 - long2ip not working with IPv6 use cidr::inet_itop $string = str_pad(long2ip($resolvRecord['start']), 14) . " - " . long2ip($resolvRecord['end']); PH::ACTIONlog( $context, $string ); } - /*foreach($resolvMap['unresolved'] as &$resolvRecord) + $unresolvedCount = count($resolvMap->unresolved); + $string = "unresolved: {$unresolvedCount} entries"; + if( $unresolvedCount > 0 ) { - PH::print_stdout( " * UNRESOLVED: {$resolvRecord->name()}" ); - }*/ + PH::print_stdout("" ); + PH::ACTIONlog( $context, $string ); + foreach($resolvMap->unresolved as &$resolvRecord) + { + $string ="UNRESOLVED: objname: '{$resolvRecord->name()}' of type: ".$resolvRecord->type(); + PH::ACTIONlog( $context, $string ); + } + } } else { diff --git a/utils/common/actions-service.php b/utils/common/actions-service.php index b2ec5970..b1fcc516 100644 --- a/utils/common/actions-service.php +++ b/utils/common/actions-service.php @@ -1375,6 +1375,35 @@ } ); +ServiceCallContext::$supportedActions[] = array( + 'name' => 'show-dstportmapping', + 'MainFunction' => function (ServiceCallContext $context) { + $object = $context->object; + + $tmp_array = array(); + $tmp_array[] = $object; + $dst_port_mapping = new ServiceDstPortMapping(); + $dst_port_mapping->mergeWithArrayOfServiceObjects( $tmp_array); + + $dst_port_mapping->countPortmapping(); + + if( count( $dst_port_mapping->tcpPortMap ) > 0 ) + { + $string = str_replace( "tcp/", "", $dst_port_mapping->tcpMappingToText()); + PH::print_stdout( $context->padding." TCP: ".$string ); + PH::print_stdout( $context->padding." TCP-counter: ".$dst_port_mapping->tcpPortCounter ); + } + + if( count( $dst_port_mapping->udpPortMap ) > 0 ) + { + $string = str_replace( "udp/", "", $dst_port_mapping->udpMappingToText()); + PH::print_stdout( $context->padding." UDP: ".$string ); + PH::print_stdout( $context->padding." UDP-counter: ".$dst_port_mapping->udpPortCounter ); + } + + } +); + ServiceCallContext::$supportedActions[] = array( 'name' => 'create-service', 'MainFunction' => function (ServiceCallContext $context) {