diff --git a/CheckPointObjects/CLIScriptBuilder.cs b/CheckPointObjects/CLIScriptBuilder.cs index 875b5fd6..fc2984f9 100644 --- a/CheckPointObjects/CLIScriptBuilder.cs +++ b/CheckPointObjects/CLIScriptBuilder.cs @@ -52,7 +52,7 @@ public static string GenerateScriptFooter(string errorsReportFileName) .Append("mgmt_cli logout -s id.txt") .Append(Environment.NewLine) .Append(Environment.NewLine) - .Append("if [ -f ").Append(errorsReportFileName).Append(" ]; then") + .Append("if [[ -f ").Append(errorsReportFileName).Append(" ]]; then") .Append(Environment.NewLine) .Append(" echo ''") .Append(Environment.NewLine) @@ -78,7 +78,7 @@ public static string GenerateRunCommandScript(string errorsReportFileName) .Append(Environment.NewLine) .Append(" eval $cmd > last_output.txt 2>&1") .Append(Environment.NewLine) - .Append(" if [ $? -ne 0 ]; then") + .Append(" if [[ $? -ne 0 ]]; then") .Append(Environment.NewLine) .Append(" echo $cmd >> ").Append(errorsReportFileName) .Append(Environment.NewLine) @@ -103,7 +103,7 @@ public static string GenerateLoginScript(string domainName, string errorsReportF var sb = new StringBuilder(); sb.Append("echo 'Logging in...'") .Append(Environment.NewLine) - .Append("if [ -f ").Append(errorsReportFileName).Append(" ]; then") + .Append("if [[ -f ").Append(errorsReportFileName).Append(" ]]; then") .Append(Environment.NewLine) .Append(" rm ").Append(errorsReportFileName) .Append(Environment.NewLine) @@ -121,7 +121,7 @@ public static string GenerateLoginScript(string domainName, string errorsReportF sb.Append("mgmt_cli login -r true -d \"").Append(domainName).Append("\" -v 1.1 > id.txt").Append(Environment.NewLine); } - sb.Append("if [ $? -ne 0 ]; then") + sb.Append("if [[ $? -ne 0 ]]; then") .Append(Environment.NewLine) .Append(" echo 'Login Failed'") .Append(Environment.NewLine) @@ -138,7 +138,7 @@ public static string GenerateLoginScript(string domainName, string errorsReportF .Append(Environment.NewLine) .Append("DOMAINS_COUNT=$($JQ -r \".total\" domains.json)") .Append(Environment.NewLine) - .Append("if [ $DOMAINS_COUNT -ne 0 ]; then") + .Append("if [[ $DOMAINS_COUNT -ne 0 ]]; then") .Append(Environment.NewLine) .Append(" echo 'This script cannot be executed on MDS. Please specify a domain name in SmartMove tool.'") .Append(Environment.NewLine) diff --git a/CheckPointObjects/CheckPointObjects.cs b/CheckPointObjects/CheckPointObjects.cs index fc391e4f..edd7c1cb 100644 --- a/CheckPointObjects/CheckPointObjects.cs +++ b/CheckPointObjects/CheckPointObjects.cs @@ -1,4 +1,4 @@ -/******************************************************************** +/******************************************************************** Copyright (c) 2017, Check Point Software Technologies Ltd. All rights reserved. @@ -19,6 +19,7 @@ limitations under the License. using System.Collections.Generic; using System.Linq; using System.Net; +using System.Text; using System.Text.RegularExpressions; using CommonUtils; @@ -45,6 +46,7 @@ public abstract class CheckPointObject public const string All = "All"; public const string All_Internet = "All_Internet"; public const string icmpProtocol = "icmp-proto"; + public const string icmp6Protocol = "IPv6-ICMP"; public string Name { get; set; } @@ -90,15 +92,15 @@ protected static string GetSafeName(string name) { return Regex.Replace(name, NameValidityRegex, "_"); } - - //escaping quote sign in script + + //escaping quote sign in script public List EscapeQuote(List members) { List resultList = new List(); foreach (string member in members) { if (member.IndexOf("\'") != -1) - resultList.Add(member.Replace("\'", "\'\\\'\'")); + resultList.Add(member.Replace("\'", "\'\\\'\'")); else resultList.Add(member); } @@ -127,7 +129,17 @@ protected static string WriteParam(string paramName, string paramValue, string d protected static string WriteListParam(string paramName, List paramValues, bool useSafeNames) { - if (paramValues.Count == 0) + return WriteListParam(paramName, paramValues, useSafeNames, 0, paramValues.Count); + } + + protected static string WriteListParam(string paramName, List paramValues, bool useSafeNames, int firstIndex, int maxSize) + { + return WriteListParam(paramName, paramValues, useSafeNames, firstIndex, maxSize, ""); + } + + protected static string WriteListParam(string paramName, List paramValues, bool useSafeNames, int firstIndex, int maxSize, string suffix) + { + if (paramValues.Count == 0 || firstIndex >= paramValues.Count || maxSize <= 0) { return ""; } @@ -137,46 +149,20 @@ protected static string WriteListParam(string paramName, List paramValue return WriteParam(paramName, paramValues[0], ""); } - string str = ""; - int i = 0; - - foreach (string paramValue in paramValues) + var sb = new StringBuilder(""); + int maxIndex = ((firstIndex + maxSize) < paramValues.Count) ? (firstIndex + maxSize) : paramValues.Count; + for (int i = firstIndex; i < maxIndex; i++) { - string val = paramValue; - if (useSafeNames) - { - val = GetSafeName(paramValue); - } - - str += string.Format("{0}.{1} \"{2}\" ", paramName, i, val); - i++; + string value = useSafeNames ? GetSafeName(paramValues[i]) : paramValues[i]; + sb.AppendFormat("{0}{1}.{2} \"{3}\" ", paramName, suffix, i, value); } - return str; + return sb.ToString(); } protected static string WriteListParamWithIndexes(string paramName, List paramValues, bool useSafeNames, int i = 0) { - if (paramValues.Count == 0) - { - return ""; - } - - string str = ""; - - foreach (string paramValue in paramValues) - { - string val = paramValue; - if (useSafeNames) - { - val = GetSafeName(paramValue); - } - - str += string.Format("{0}.{1} \"{2}\" ", paramName, i, val); - i++; - } - - return str; + return WriteListParam(paramName, paramValues, useSafeNames, i, paramValues.Count); } } @@ -251,23 +237,37 @@ public class CheckPoint_Network : CheckPointObject { public string Subnet { get; set; } public string Netmask { get; set; } + public string MaskLength { get; set; } + + public CheckPoint_Network() : base() + { + MaskLength = ""; + } public override IPRanges GetIPRanges() { - return new IPRanges(new IPRange(IPNetwork.Parse(Subnet, Netmask))); + if (!string.IsNullOrEmpty(Netmask)) + { + return new IPRanges(new IPRange(IPNetwork.Parse(Subnet, Netmask))); + } + else + { + return new IPRanges(new IPRange(IPNetwork.Parse(String.Format("{0}/{1}", Subnet, MaskLength)))); + } } public override string ToCLIScript() { return "add network " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") + WriteParam("subnet", Subnet, "") - + WriteParam("subnet-mask", Netmask , "") + + WriteParam("subnet-mask", Netmask, "") + + WriteParam("mask-length", MaskLength, "") + WriteListParam("tags", Tags, true); } public override string ToCLIScriptInstruction() { - return "create network [" + Name + "]: subnet [" + Subnet + "] mask [" + Netmask + "]"; + return "create network [" + Name + "]: subnet [" + Subnet + "] mask [" + Netmask + "] mask-lenght [" + MaskLength + "]"; } } @@ -298,26 +298,36 @@ public override string ToCLIScriptInstruction() public class CheckPoint_NetworkGroup : CheckPointObject { public List Members = new List(); - - public bool IsPanoramaDeviceGroup = false; + + public bool IsPanoramaDeviceGroup = false; /// /// This property is used to overcome the problematic order of objects creation for /// GroupWithExclusion and NetworkGroup types cross-referencing each other. /// public bool CreateAfterGroupsWithExclusion { get; set; } + public int MembersPublishIndex { get; set; } + public int MembersMaxPublishSize { get; set; } + + public CheckPoint_NetworkGroup() : base() + { + MembersPublishIndex = 0; + MembersMaxPublishSize = Int32.MaxValue; + } public override string ToCLIScript() { - return "add group " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") - + WriteListParam("members", Members, true) + return (MembersPublishIndex == 0 ? "add " : "set ") + "group " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") + + WriteListParam("members", Members, true, MembersPublishIndex, MembersMaxPublishSize, MembersPublishIndex == 0 ? "" : ".add") + WriteListParam("tags", Tags, true); } public override string ToCLIScriptInstruction() { - return "create network group [" + Name + "]: " + Members.Count + " members"; + int index = ((MembersPublishIndex + MembersMaxPublishSize) > Members.Count) ? Members.Count : MembersPublishIndex + MembersMaxPublishSize; + return (MembersPublishIndex == 0 ? "create " : "update ") + "network group [" + Name + "]: " + index + "/" + Members.Count + " members"; } + } public class CheckPoint_GroupWithExclusion : CheckPointObject @@ -368,6 +378,7 @@ public override string ToCLIScript() + WriteParam("port", Port, "") + WriteParam("source-port", SourcePort, "") + WriteParam("session-timeout", SessionTimeout, "0") + + ((SessionTimeout != null && !SessionTimeout.Equals("0")) ? WriteParam("use-default-session-timeout", "false", "") : "") + WriteListParam("tags", Tags, true); } @@ -389,6 +400,7 @@ public override string ToCLIScript() + WriteParam("port", Port, "") + WriteParam("source-port", SourcePort, "") + WriteParam("session-timeout", SessionTimeout, "0") + + ((SessionTimeout != null && !SessionTimeout.Equals("0")) ? WriteParam("use-default-session-timeout", "false", "") : "") + WriteListParam("tags", Tags, true); } @@ -410,6 +422,7 @@ public override string ToCLIScript() + WriteParam("port", Port, "") + WriteParam("source-port", SourcePort, "") + WriteParam("session-timeout", SessionTimeout, "0") + + ((SessionTimeout != null && !SessionTimeout.Equals("0")) ? WriteParam("use-default-session-timeout", "false", "") : "") + WriteListParam("tags", Tags, true); } @@ -476,6 +489,15 @@ public class CheckPoint_OtherService : CheckPointObject { public string IpProtocol { get; set; } + public CheckPoint_OtherService() : base() { } + public CheckPoint_OtherService (string name, string ipprotocol, string comments, List tags) : base() + { + Name = name; + IpProtocol = ipprotocol; + Comments = comments; + Tags = tags; + } + public override string ToCLIScript() { return "add service-other " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") @@ -493,18 +515,29 @@ public override string ToCLIScriptInstruction() public class CheckPoint_ServiceGroup : CheckPointObject { public List Members = new List(); + public int MembersPublishIndex { get; set; } + public int MembersMaxPublishSize { get; set; } + + public CheckPoint_ServiceGroup() : base() + { + MembersPublishIndex = 0; + MembersMaxPublishSize = Int32.MaxValue; + } public override string ToCLIScript() { - return "add service-group " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") - + WriteListParam("members", Members, true) + return (MembersPublishIndex == 0 ? "add " : "set ") + "service-group " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") + + WriteListParam("members", Members, true, MembersPublishIndex, MembersMaxPublishSize, MembersPublishIndex == 0 ? "" : ".add") + WriteListParam("tags", Tags, true); } public override string ToCLIScriptInstruction() { - return "create service group [" + Name + "]: " + Members.Count + " members"; + //index for comments + int index = ((MembersPublishIndex + MembersMaxPublishSize) > Members.Count) ? Members.Count : MembersPublishIndex + MembersMaxPublishSize; + return (MembersPublishIndex == 0 ? "create " : "update ") + "service group [" + Name + "]: " + index + "/" + Members.Count + " members"; } + } public class CheckPoint_ApplicationGroup : CheckPointObject @@ -540,7 +573,7 @@ public enum RecurrencePatternEnum { None, Daily, Weekly, Monthly }; public string EndDate { get; set; } public string EndTime { get; set; } public double EndPosix { get; set; } - + public bool HoursRangesEnabled_1 { get; set; } public string HoursRangesFrom_1 { get; set; } public string HoursRangesTo_1 { get; set; } @@ -560,25 +593,25 @@ public enum RecurrencePatternEnum { None, Daily, Weekly, Monthly }; public override string ToCLIScript() { return "add time " + WriteParam("name", SafeName(), "") + WriteParam("comments", Comments, "") - - + WriteParam("start-now", StartNow.ToString().ToLower(), "") - + WriteParam("start.date", StartDate, "") + + + WriteParam("start-now", StartNow.ToString().ToLower(), "") + + WriteParam("start.date", StartDate, "") + WriteParam("start.time", StartTime, "") + WriteParam("start.posix", (StartPosix > 0 ? "" + StartPosix : ""), "") - + WriteParam("end-never", EndNever.ToString().ToLower(), "") - + WriteParam("end.date", EndDate, "") + + WriteParam("end-never", EndNever.ToString().ToLower(), "") + + WriteParam("end.date", EndDate, "") + WriteParam("end.time", EndTime, "") + WriteParam("end.posix", (EndPosix > 0 ? "" + EndPosix : ""), "") - + WriteParam("hours-ranges.1.enabled", (HoursRangesEnabled_1 ? HoursRangesEnabled_1.ToString().ToLower() : ""), "") - + WriteParam("hours-ranges.1.from", HoursRangesFrom_1, "") + + WriteParam("hours-ranges.1.enabled", (HoursRangesEnabled_1 ? HoursRangesEnabled_1.ToString().ToLower() : ""), "") + + WriteParam("hours-ranges.1.from", HoursRangesFrom_1, "") + WriteParam("hours-ranges.1.to", HoursRangesTo_1, "") + WriteParam("hours-ranges.2.enabled", (HoursRangesEnabled_2 ? HoursRangesEnabled_2.ToString().ToLower() : ""), "") + WriteParam("hours-ranges.2.from", HoursRangesFrom_2, "") - + WriteParam("hours-ranges.2.to", HoursRangesTo_2, "") - + + WriteParam("hours-ranges.2.to", HoursRangesTo_2, "") + + WriteParam("hours-ranges.3.enabled", (HoursRangesEnabled_3 ? HoursRangesEnabled_3.ToString().ToLower() : ""), "") + WriteParam("hours-ranges.3.from", HoursRangesFrom_3, "") + WriteParam("hours-ranges.3.to", HoursRangesTo_3, "") @@ -595,11 +628,11 @@ public override string ToCLIScriptInstruction() { return "create time [" + Name + "]"; } - - public CheckPoint_Time Clone() + + public CheckPoint_Time Clone() { var newTime = new CheckPoint_Time(); - + newTime.Name = Name; newTime.Comments = Comments; newTime.StartNow = StartNow; @@ -660,7 +693,7 @@ public class CheckPoint_AccessRole : CheckPointObject public override string ToCLIScript() { - if(Networks.Count == 0) + if (Networks.Count == 0) { Networks.Add("any"); } @@ -717,7 +750,7 @@ public CheckPoint_Rule() DestinationNegated = false; ConversionComments = ""; } - + public override string ToCLIScript() { string actionName = ""; @@ -752,7 +785,7 @@ public override string ToCLIScript() + WriteParam("position", "top", "") + WriteParam("inline-layer", SubPolicyName, "") + WriteParam("name", Name, "") - + WriteListParam("install-on", (from o in Target select o).ToList(), true) + + WriteListParam("install-on", (from o in Target select o).ToList(), true) + WriteParam("custom-fields.field-1", ConversionComments.Substring(0, Math.Min(ConversionComments.Length, 150)), ""); } @@ -776,7 +809,7 @@ public CheckPoint_Rule Clone() newRule.ConvertedCommandId = ConvertedCommandId; newRule.ConversionIncidentType = ConversionIncidentType; - foreach(CheckPointObject obj in Source) + foreach (CheckPointObject obj in Source) { newRule.Source.Add(obj); } @@ -804,7 +837,7 @@ public CheckPoint_Rule Clone() public bool CompareTo(CheckPoint_Rule other) { if (Enabled != other.Enabled || - Action != other.Action || + Action != other.Action || Track != other.Track || SourceNegated != other.SourceNegated || DestinationNegated != other.DestinationNegated) @@ -874,7 +907,7 @@ protected virtual string WriteParamWithIndexesForApplications() { return null; } - + protected virtual string WriteServicesParams() { return WriteListParam("service", (from o in Service select o.Name).ToList(), true); @@ -915,16 +948,17 @@ protected override string WriteParamWithIndexesForApplications() { return WriteListParamWithIndexes("service", (from o in Application select o.Name).ToList(), false, Service.Count); } - - protected override string WriteServicesParams() - { + + protected override string WriteServicesParams() + { return WriteListParamWithIndexes("service", (from o in Service select o.Name).ToList(), true, 0);//add indexes to services in case applications present as well } //specific extension for cloning applications protected override void CloneApplicationsToRule(CheckPoint_Rule newRule) { - if (newRule is CheckPoint_RuleWithApplication) { + if (newRule is CheckPoint_RuleWithApplication) + { foreach (CheckPointObject obj in Application) { ((CheckPoint_RuleWithApplication)newRule).Application.Add(obj); @@ -939,7 +973,7 @@ protected override bool CompareApplications(CheckPoint_Rule other) { return CompareLists(Application, ((CheckPoint_RuleWithApplication)other).Application); } - + return false; } @@ -974,7 +1008,7 @@ public override string ToCLIScriptInstruction() public class CheckPoint_NAT_Rule : CheckPointObject { - public enum NatMethod { Static, Hide }; + public enum NatMethod { Static, Hide, Nat64, Nat46 }; public bool Enabled { get; set; } public string Package { get; set; } @@ -1040,8 +1074,8 @@ public CheckPoint_NAT_Rule Clone() public class CheckPoint_Package : CheckPointObject { - public string NameOfAccessLayer - { + public string NameOfAccessLayer + { get { return Name + " Network"; } } @@ -1071,3 +1105,4 @@ public int TotalRules() } } } + diff --git a/CheckPointObjects/CheckPointObjectsRepository.cs b/CheckPointObjects/CheckPointObjectsRepository.cs index 30c0cb8e..8a650745 100644 --- a/CheckPointObjects/CheckPointObjectsRepository.cs +++ b/CheckPointObjects/CheckPointObjectsRepository.cs @@ -54,7 +54,7 @@ public ObjectInfo(CheckPointObject cpObject, bool isPredefined) /// public void Initialize() { - string[] names = { CheckPointObject.Any, CheckPointObject.icmpProtocol, CheckPointObject.All_Internet }; // general objects + string[] names = { CheckPointObject.Any, CheckPointObject.icmpProtocol, CheckPointObject.All_Internet, CheckPointObject.icmp6Protocol }; // general objects foreach (string name in names) { var cpPredifinedObject = new CheckPoint_PredifinedObject { Name = name }; diff --git a/CiscoMigration/CiscoCommands.cs b/CiscoMigration/CiscoCommands.cs index f9cbffc3..35d2d6b5 100644 --- a/CiscoMigration/CiscoCommands.cs +++ b/CiscoMigration/CiscoCommands.cs @@ -1,2375 +1,2411 @@ -/******************************************************************** -Copyright (c) 2017, Check Point Software Technologies Ltd. -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. -********************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using CommonUtils; - -namespace CiscoMigration -{ - public enum ProtocolType { NA, Ip, Icmp, Udp, Tcp, KnownOtherIpProtocol, ReferenceObject }; - public enum TcpUdpPortOperatorType { NA, All, Lt, Gt, Eq, Neq, Range, ReferenceObject }; - public enum ServiceDirection { Source, Destination }; - - public interface ICiscoCommand - { - string Name(); - void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases); - } - - /// - /// Represents a basic Cisco command. - /// Each derived command auto-parses the appropriate configuration line text according to its "name" (via reflection mechanism). - /// Some commands may have child commands (network group commad has child network object commands). - /// The "Id" property is the configuration line number. - /// The "ParentId" property is the parent configuration line number. - /// The "CiscoId" property is the user defined name of the command. - /// - public class CiscoCommand : ICiscoCommand - { - public const string InterfacePrefix = "Interface_"; - public const string Any = "any"; - - private string _text = ""; - private string[] _words; - - public string Text - { - get { return _text; } - set - { - _text = value; - - string trimmedText = _text.Trim(); - char[] delimiterChars = { ' ', '\t' }; - - // Replace multiple spaces with a single space - trimmedText = Regex.Replace(trimmedText, @"\s+", " "); - - _words = trimmedText.Split(delimiterChars); - } - } - - public int IndentationLevel - { - get - { - if (Text.Length == 0) - { - return 0; - } - - int pos = 0; - while (Text.Substring(pos, 1) == " ") - { - pos++; - } - return pos; - } - } - - public string FirstWord - { - get - { - if (_words != null && _words.Any()) - { - // This is a special handling!!! - // There are several commands that have the first word "ip"... - if (_words[0] == "ip") - { - if (_words.Count() > 1 && _words[1] == "address") - { - return _words[0] + " " + _words[1]; - } - if (_words.Count() > 3 && _words[1] == "verify" && _words[2] == "reverse-path" && _words[3] == "interface") - { - return _words[0] + " " + _words[1] + " " + _words[2] + " " + _words[3]; - } - } - else - { - return _words[0]; - } - } - - return ""; - } - } - - public int Id { get; set; } - public int? ParentId { get; set; } - public string CiscoId { get; set; } - public string Description { get; set; } - public string Tag { get; set; } - public string DataForNextElement { get; set; } - public bool KnownCommand { get; set; } - public bool NotAnInterestingCommand { get; set; } - public ConversionIncidentType ConversionIncidentType { get; set; } - public string ConversionIncidentMessage { get; set; } - public List Children { get; set; } - - public CiscoCommand() - { - CiscoId = ""; - Description = ""; - DataForNextElement = ""; - } - - public string GetParam(int pos) - { - if (_words == null || _words.Length <= pos) - { - return ""; - } - - return _words[pos]; - } - - public List GetParams(int pos) - { - var res = new List(); - - if (_words == null || !_words.Any()) - { - return res; - } - - for (int i = 0; i < _words.Length; i++) - { - if (i >= pos) - { - res.Add(_words[i]); - } - } - - return res; - } - - public int GetParamPosition(string paramName) - { - if (_words == null || !_words.Any()) - { - return -1; - } - - int pos = 0; - foreach (string word in _words) - { - if (word == paramName) - { - return pos; - } - pos++; - } - - return -1; - } - - public List Flatten() - { - var res = new List(); - res.Add(this); - - if (Children != null) - { - foreach (CiscoCommand child in Children) - { - foreach (CiscoCommand flattenchild in child.Flatten()) - { - res.Add(flattenchild); - } - } - } - - return res; - } - - public virtual string Name() { return ""; } - - public virtual void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - if (command.Children != null) - { - foreach (CiscoCommand child in command.Children) - { - if (child.Name() == "description") - { - Description = child.Description; - } - } - } - - ConversionIncidentType = ConversionIncidentType.None; - ConversionIncidentMessage = ""; - } - } - - public class Cisco_Description : CiscoCommand - { - public Cisco_Description() - { - NotAnInterestingCommand = true; - } - - public override string Name() { return "description"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - if (!string.IsNullOrEmpty(command.Text)) - { - Description = command.Text.Trim().Substring(Name().Length + 1); - } - - } - } - - public class Cisco_ASA : CiscoCommand - { - public string Version { get; set; } - - public override string Name() { return "ASA"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - const string version = "version"; - if (!string.IsNullOrEmpty(command.Text) && command.GetParam(1).ToLower() == version) - { - Version = command.Text.Trim().Substring(Name().Length + version.Length + 2); - } - else - { - Version = ""; - } - } - } - - public class Cisco_Alias : CiscoCommand - { - public override string Name() { return "name"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - string real = command.GetParam(1); - string alias = command.GetParam(2); - - if (!string.IsNullOrEmpty(alias) && !string.IsNullOrEmpty(real) && !aliases.ContainsKey(alias)) - { - aliases.Add(alias, real); - } - } - } - - public class Cisco_SSH : CiscoCommand - { - public string IpAddress { get; set; } - public string Netmask { get; set; } - public string Interface { get; set; } - - public override string Name() { return "ssh"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - IpAddress = ""; - Netmask = ""; - Interface = ""; - - string commandParam = command.GetParam(1); - if (NetworkUtils.IsValidIp(commandParam)) - { - IpAddress = commandParam; - } - else - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "IPv4 address was expected, but '" + commandParam + "' was found."; - return; - } - - commandParam = command.GetParam(2); - if (NetworkUtils.IsValidNetmask(commandParam)) - { - Netmask = commandParam; - } - else - { - IpAddress = ""; - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "IPv4 netmask was expected, but " + commandParam + " was found."; - return; - } - - Interface = command.GetParam(3); - } - } - - public class Cisco_Hostname : CiscoCommand - { - public string HostName { get; set; } - - public override string Name() { return "hostname"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - HostName = command.GetParam(1); - } - } - - public class Cisco_Object : CiscoCommand - { - public enum ObjectTypes { NA, Fqdn, Host, Network, Range, TcpService, UdpService, IcmpService, KnownOtherService }; - - public ObjectTypes ObjectType { get; set; } - public string Fqdn { get; set; } - public string HostAddress { get; set; } - public string Network { get; set; } - public string Netmask { get; set; } - public string RangeFrom { get; set; } - public string RangeTo { get; set; } - public bool IsDestination { get; set; } - public string ServiceProtocol { get; set; } - public string ServiceOperator { set; get; } - public string ServicePort { get; set; } - - public override string Name() { return "object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - CiscoId = command.GetParam(2); - ObjectType = ObjectTypes.NA; - - switch (command.GetParam(1)) - { - case "network": - ParseNetworks(); - break; - - case "service": - ParseServices(); - break; - - default: - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Unrecognized object type (" + command.GetParam(1) + ")"; - break; - } - } - - private void ParseNetworks() - { - if (Children == null) - { - return; - } - - int found = 0; - - foreach (CiscoCommand child in Children) - { - switch (child.Name()) - { - case "fqdn": - ObjectType = ObjectTypes.Fqdn; - Fqdn = ((Cisco_Fqdn)child).Fqdn; - found++; - break; - - case "host": - ObjectType = ObjectTypes.Host; - HostAddress = ((Cisco_Host)child).HostAddress; - found++; - break; - - case "subnet": - ObjectType = ObjectTypes.Network; - Network = ((Cisco_Subnet)child).Network; - Netmask = ((Cisco_Subnet)child).Netmask; - found++; - break; - - case "range": - ObjectType = ObjectTypes.Range; - RangeFrom = ((Cisco_Range)child).RangeFrom; - RangeTo = ((Cisco_Range)child).RangeTo; - found++; - break; - } - - if (found == 1) - { - if (child.ConversionIncidentType != ConversionIncidentType.None) - { - ConversionIncidentType = child.ConversionIncidentType; - ConversionIncidentMessage = child.ConversionIncidentMessage; - } - } - } - - if (found > 1) - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "An Object (network) can only hold one fqdn, host, range or subnet"; - Console.WriteLine(ConversionIncidentMessage); - } - } - - private void ParseServices() - { - if (Children == null) - { - return; - } - - int found = 0; - - foreach (CiscoCommand child in Children) - { - if (child.Name() == "service") - { - found++; - - var service = (Cisco_Service)child; - ServiceProtocol = service.Protocol; - ServiceOperator = service.Operator; - ServicePort = service.Port; - IsDestination = service.IsDestination; - - if (service.ConversionIncidentType != ConversionIncidentType.None) - { - ConversionIncidentType = service.ConversionIncidentType; - ConversionIncidentMessage = service.ConversionIncidentMessage; - } - - switch (ServiceProtocol) - { - case "ip": - // Predefined "any" object. No special handling... - break; - - case "icmp": - ObjectType = ObjectTypes.IcmpService; - break; - - case "tcp": - ObjectType = ObjectTypes.TcpService; - break; - - case "udp": - ObjectType = ObjectTypes.UdpService; - break; - - default: - // No need to check also for CiscoKnownServices.IsKnownServiceNumber here, - // because it is already done in Cisco_Service class!!! - if (CiscoKnownServices.IsKnownService(ServiceProtocol)) - { - ObjectType = ObjectTypes.KnownOtherService; - } - else - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Unrecognized service protocol (" + ServiceProtocol + ")"; - Console.WriteLine(ConversionIncidentMessage); - } - break; - } - } - } - - if (found > 1) - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "An Object (service) can only hold one service"; - Console.WriteLine(ConversionIncidentMessage); - } - } - } - - public class Cisco_Fqdn : CiscoCommand - { - public string Fqdn { get; set; } - - public override string Name() { return "fqdn"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - Fqdn = (command.GetParam(1) == "v4") ? command.GetParam(2) : command.GetParam(1); - } - } - - public class Cisco_Host : CiscoCommand - { - public string HostAddress { get; set; } - - public override string Name() { return "host"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - HostAddress = command.GetParam(1); - if (!NetworkUtils.IsValidIp(HostAddress)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid host IP address (" + HostAddress + "). Using IP 1.1.1.1."; - Console.WriteLine(ConversionIncidentMessage); - - HostAddress = "1.1.1.1"; - } - } - } - - public class Cisco_Subnet : CiscoCommand - { - public string Network { get; set; } - public string Netmask { get; set; } - - public override string Name() { return "subnet"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - Network = command.GetParam(1); - Netmask = command.GetParam(2); - - if (!NetworkUtils.IsValidIp(Network) || !NetworkUtils.IsValidNetmask(Netmask)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid IP subnet (" + Network + "/" + Netmask + "). Using IP subnet 1.1.1.0/255.255.255.0."; - Console.WriteLine(ConversionIncidentMessage); - - Network = "1.1.1.0"; - Netmask = "255.255.255.0"; - } - } - } - - public class Cisco_Range : CiscoCommand - { - public string RangeFrom { get; set; } - public string RangeTo { get; set; } - - public override string Name() { return "range"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - RangeFrom = command.GetParam(1); - if (!NetworkUtils.IsValidIp(RangeFrom)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid range starting IP address (" + RangeFrom + "). Using IP 0.0.0.0."; - Console.WriteLine(ConversionIncidentMessage); - - RangeFrom = "0.0.0.0"; - } - - RangeTo = command.GetParam(2); - if (!NetworkUtils.IsValidIp(RangeTo)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid range ending IP address (" + RangeTo + "). Using IP 255.255.255.255."; - Console.WriteLine(ConversionIncidentMessage); - - RangeTo = "255.255.255.255"; - } - } - } - - public class Cisco_Service : CiscoCommand - { - public string Protocol { get; set; } - public bool IsDestination { get; set; } - public string Port { get; set; } - public string Operator { get; set; } - - public override string Name() { return "service"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - // Parsing Options: - //----------------- - // 1. service protocol_name_or_number - // 2. service {icmp | icmp6} [icmp-type] - // 3. service {tcp | udp} [source operator port] [destination operator port] - //----------------- - - Protocol = command.GetParam(1); - - IsDestination = false; - Port = ""; - Operator = ""; - - switch (Protocol) - { - case "ip": - IsDestination = true; - break; - - case "icmp": - case "icmp6": - IsDestination = true; - Protocol = "icmp"; - Operator = "eq"; - Port = CiscoKnownServices.ConvertIcmpServiceToType(command.GetParam(2)); - break; - - case "tcp": - case "udp": - IsDestination = (command.GetParam(2) == "destination"); - Operator = command.GetParam(3); - Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(4)); - - int nextParamId = 5; // we need this because of 'range' operator - - if (Operator == "range") - { - Operator = "eq"; - Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(5)); - nextParamId = 6; // !!! - } - - if (!IsDestination && command.GetParam(nextParamId) == "destination") - { - // "service tcp source eq ssh destination eq ssh" ---> wrong!!! ---> ignore source!!! - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Cannot convert a service defined as both source service and destination service. Ignoring source service."; - Console.WriteLine(ConversionIncidentMessage); - - IsDestination = true; - Operator = command.GetParam(nextParamId + 1); - Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 2)); - - if (Operator == "range") - { - Operator = "eq"; - Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 3)); - } - } - - if (string.IsNullOrEmpty(Operator) || string.IsNullOrEmpty(Port)) - { - // Use ALL tcp/udp ports if nothing specified!!! - IsDestination = true; - Operator = "all"; - Port = "1-65535"; - } - break; - - default: - IsDestination = true; - - string serviceName; - if (CiscoKnownServices.IsKnownService(Protocol)) - { - Port = CiscoKnownServices.ConvertServiceToPort(Protocol); - } - else if (CiscoKnownServices.IsKnownServiceNumber(Protocol, out serviceName)) // protocol number is used!!! - { - Port = Protocol; - Protocol = serviceName; - } - else - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Unrecognized service protocol (" + Protocol + ")"; - Console.WriteLine(ConversionIncidentMessage); - } - break; - } - } - } - - public class Cisco_NetworkObject : CiscoCommand - { - public string IpAddress { get; set; } - public string Netmask { get; set; } - public string ReferencedObject { get; set; } - - public override string Name() { return "network-object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - IpAddress = ""; - Netmask = ""; - ReferencedObject = ""; - - switch (command.GetParam(1)) - { - case "object": - ReferencedObject = command.GetParam(2); - break; - - case "host": - string ipAddressOrObjectName = command.GetParam(2); - if (ciscoIds.ContainsKey(ipAddressOrObjectName)) - { - ReferencedObject = ipAddressOrObjectName; - } - else - { - IpAddress = aliases.ContainsKey(ipAddressOrObjectName) ? aliases[ipAddressOrObjectName] : ipAddressOrObjectName; - if (!NetworkUtils.IsValidIp(IpAddress)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid IP address (" + IpAddress + "). Using IP 1.1.1.1."; - Console.WriteLine(ConversionIncidentMessage); - - IpAddress = "1.1.1.1"; - } - - Netmask = "255.255.255.255"; - } - break; - - default: - // subnet - IpAddress = command.GetParam(1); - if (aliases.ContainsKey((IpAddress))) - { - IpAddress = aliases[IpAddress]; - } - Netmask = command.GetParam(2); - - if (!NetworkUtils.IsValidIp(IpAddress) || !NetworkUtils.IsValidNetmask(Netmask)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid IP subnet (" + IpAddress + "/" + Netmask + "). Using IP subnet 1.1.1.0/255.255.255.0."; - Console.WriteLine(ConversionIncidentMessage); - - IpAddress = "1.1.1.0"; - Netmask = "255.255.255.0"; - } - break; - } - } - } - - public class Cisco_ProtocolObject : CiscoCommand - { - public string ProtocolName { get; set; } - - public override string Name() { return "protocol-object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - ProtocolName = command.GetParam(1); - } - } - - public class Cisco_PortObject : CiscoCommand - { - public string Port { get; set; } - - public override string Name() { return "port-object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - Port = ""; - - string portOperator = command.GetParam(1); - - switch (portOperator) - { - case "eq": - Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(2)); - break; - - case "range": - Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(2)) + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(3)); - break; - } - } - } - - public class Cisco_ServiceObject : CiscoCommand - { - public string Protocol { get; set; } - public bool IsDestination { get; set; } - public string Port { get; set; } - public string Operator { get; set; } - public string RefObjectName { get; set; } - - public override string Name() { return "service-object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - // Parsing Options: - //----------------- - // 1. service-object object object_name - // 2. service-object protocol_name_or_number - // 3. service-object {icmp | icmp6} [icmp-type] - // 4. service-object {tcp | udp | tcp-udp} [source operator port] [destination operator port] - //----------------- - - Protocol = command.GetParam(1); - - IsDestination = false; - Port = ""; - Operator = ""; - RefObjectName = ""; - - switch (Protocol) - { - case "object": - RefObjectName = command.GetParam(2); - Protocol = ""; - break; - - case "ip": - IsDestination = true; - break; - - case "icmp": - case "icmp6": - IsDestination = true; - Protocol = "icmp"; - Operator = "eq"; - Port = CiscoKnownServices.ConvertIcmpServiceToType(command.GetParam(2)); - break; - - case "tcp": - case "udp": - case "tcp-udp": - IsDestination = (command.GetParam(2) == "destination"); - Operator = command.GetParam(3); - Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(4)); - - int nextParamId = 5; // we need this because of 'range' operator - - if (Operator == "range") - { - Operator = "eq"; - Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(5)); - nextParamId = 6; // !!! - } - - if (!IsDestination && command.GetParam(nextParamId) == "destination") - { - // "service-object tcp source eq ssh destination eq ssh" ---> wrong!!! ---> ignore source!!! - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Cannot convert a service defined as both source service and destination service. Ignoring source service."; - Console.WriteLine(ConversionIncidentMessage); - - IsDestination = true; - Operator = command.GetParam(nextParamId + 1); - Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 2)); - - if (Operator == "range") - { - Operator = "eq"; - Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 3)); - } - } - - if (string.IsNullOrEmpty(Operator) || string.IsNullOrEmpty(Port)) - { - // Use ALL tcp/udp ports if nothing specified!!! - IsDestination = true; - Operator = "all"; - Port = "1-65535"; - } - break; - - default: - IsDestination = true; - - string serviceName; - if (CiscoKnownServices.IsKnownService(Protocol)) - { - Port = CiscoKnownServices.ConvertServiceToPort(Protocol); - } - else if (CiscoKnownServices.IsKnownServiceNumber(Protocol, out serviceName)) // protocol number is used!!! - { - Port = Protocol; - Protocol = serviceName; - } - else - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Unrecognized service protocol (" + Protocol + ")"; - Console.WriteLine(ConversionIncidentMessage); - } - break; - } - } - } - - public class Cisco_IcmpObject : CiscoCommand - { - public string IcmpType { get; set; } - - public override string Name() { return "icmp-object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - IcmpType = command.GetParam(1); - } - } - - public class Cisco_ReferenceGroupObject : CiscoCommand - { - public string ReferenceId { get; set; } - - public override string Name() { return "group-object"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - ReferenceId = command.GetParam(1); - } - } - - public class Cisco_GroupObject : CiscoCommand - { - public enum Group_Type { NA, Service, Protocol, Icmp, Network }; - - private Dictionary _ciscoIds; - - public Group_Type GroupType { get; set; } - public string ServiceProtocol { get; set; } - - public List Protocols = new List(); - public List IcmpTypes = new List(); - public List MembersGroupNames = new List(); - public List MemberObjects = new List(); - - public override string Name() { return "object-group"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - _ciscoIds = ciscoIds; - - CiscoId = command.GetParam(2); - ServiceProtocol = ""; - - switch (command.GetParam(1)) - { - case "service": - GroupType = Group_Type.Service; - break; - - case "protocol": - GroupType = Group_Type.Protocol; - break; - - case "icmp-type": - GroupType = Group_Type.Icmp; - break; - - case "network": - GroupType = Group_Type.Network; - break; - - default: - GroupType = Group_Type.NA; - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Unrecognized group type (" + command.GetParam(1) + ")"; - return; - } - - if (GroupType == Group_Type.Service) - { - ServiceProtocol = command.GetParam(3); - } - - if (command.Children == null) - { - return; - } - - foreach (CiscoCommand child in command.Children) - { - bool hasValidChild = true; - - switch (child.Name()) - { - case "protocol-object": - Protocols.Add(((Cisco_ProtocolObject)child).ProtocolName); - break; - - case "port-object": - MemberObjects.Add((Cisco_PortObject)child); - break; - - case "icmp-object": - IcmpTypes.Add(((Cisco_IcmpObject)child).IcmpType); - break; - - case "group-object": - MembersGroupNames.Add(((Cisco_ReferenceGroupObject)child).ReferenceId); - break; - - case "network-object": - MemberObjects.Add((Cisco_NetworkObject)child); - break; - - case "service-object": - MemberObjects.Add((Cisco_ServiceObject)child); - break; - - default: - hasValidChild = false; - break; - } - - if (hasValidChild) - { - if (child.ConversionIncidentType != ConversionIncidentType.None) - { - ConversionIncidentType = child.ConversionIncidentType; - ConversionIncidentMessage = child.ConversionIncidentMessage; - } - } - } - } - - public List GetChildServices() - { - var services = new List(); - - if (Children != null) - { - foreach (CiscoCommand child in Children) - { - if (child.Name() == "service-object") - { - services.Add((Cisco_ServiceObject)child); - } - else if (child.Name() == "group-object") - { - if (_ciscoIds.ContainsKey(((Cisco_ReferenceGroupObject)child).ReferenceId)) - { - var referencedGroupObject = (Cisco_GroupObject)_ciscoIds[((Cisco_ReferenceGroupObject)child).ReferenceId]; - var referencedGroupServices = referencedGroupObject.GetChildServices(); - - foreach (Cisco_ServiceObject referencedService in referencedGroupServices) - { - if (!services.Contains(referencedService)) - { - services.Add(referencedService); - } - } - } - } - } - } - - return services; - } - - public List GetChildPorts() - { - var ports = new List(); - - if (Children != null) - { - foreach (CiscoCommand child in Children) - { - if (child.Name() == "port-object") - { - ports.Add((Cisco_PortObject)child); - } - else if (child.Name() == "group-object") - { - if (_ciscoIds.ContainsKey(((Cisco_ReferenceGroupObject)child).ReferenceId)) - { - var referencedGroupObject = (Cisco_GroupObject)_ciscoIds[((Cisco_ReferenceGroupObject)child).ReferenceId]; - var referencedGroupPorts = referencedGroupObject.GetChildPorts(); - - foreach (Cisco_PortObject referencedPort in referencedGroupPorts) - { - if (!ports.Contains(referencedPort)) - { - ports.Add(referencedPort); - } - } - } - } - } - } - - return ports; - } - } - - public class Cisco_SecurityLevel : CiscoCommand - { - public string Value { get; set; } - - public override string Name() { return "security-level"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - Value = command.GetParam(1); - } - } - - public class Cisco_NameIf : CiscoCommand - { - public string Value { get; set; } - - public override string Name() { return "nameif"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - Value = InterfacePrefix + command.GetParam(1); - } - } - - public class Cisco_VLan : CiscoCommand - { - public string Value { get; set; } - - public override string Name() { return "vlan"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - Value = command.GetParam(1); - } - } - - public class Cisco_IP : CiscoCommand - { - public string IpAddress { get; set; } - public string Netmask { get; set; } - - public override string Name() { return "ip address"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - IpAddress = ""; - Netmask = ""; - - if (command.GetParam(1) == "address") - { - IpAddress = command.GetParam(2); - Netmask = command.GetParam(3); - } - } - } - - public class Cisco_Shutdown : CiscoCommand - { - public bool IsShutdown { get; set; } - - public override string Name() { return "shutdown"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - IsShutdown = (command.GetParam(0) == "shutdown"); - } - } - - public class Cisco_ManagementOnly : CiscoCommand - { - public bool IsManagementOnly { get; set; } - - public override string Name() { return "management-only"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - IsManagementOnly = (command.GetParam(0) == "management-only"); - } - } - - public class Cisco_TimeRange : CiscoCommand - { - public enum Weekdays { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; - - private string _timeRangeName; - - private string _startDateTime; - private string _endDateTime; - - private List _periodicsList; - - public string TimeRangeName - { - get { return _timeRangeName; } - } - - public string StartDateTime - { - get { return _startDateTime; } - } - - public string EndDateTime - { - get { return _endDateTime; } - } - - public List PeriodicsList - { - get { return _periodicsList; } - } - - public override string Name() { return "time-range"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - _periodicsList = new List(); - - _timeRangeName = this.GetParam(1); - - foreach(CiscoCommand child in Children) - { - if(child.FirstWord.Equals("absolute")) - { - int startIndex = child.Text.IndexOf("start"); - int endIndex = child.Text.IndexOf("end"); - if(startIndex > -1 && endIndex > -1) - { - _startDateTime = child.Text.Substring("absolute".Length + "start".Length + 2, endIndex - startIndex - "start".Length).Trim(); - _endDateTime = child.Text.Substring(endIndex + "end".Length).Trim(); - } - else if (startIndex > -1 && endIndex == -1) - { - _startDateTime = child.Text.Substring("absolute".Length + "start".Length + 2).Trim(); - } - else if(startIndex == -1 && endIndex > -1) - { - _endDateTime = child.Text.Substring("absolute".Length + "end".Length + 2).Trim(); - } - } - - if (child.FirstWord.Equals("periodic")) - { - string period = child.Text.Substring("periodic".Length + 1).Trim(); - - string[] daysTimes = period.Trim().Split(new string[] { "to" }, StringSplitOptions.RemoveEmptyEntries); - - string[] daysTimes_1 = daysTimes[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); - string[] daysTimes_2 = daysTimes[1].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); - - if (daysTimes_1.Length == 2 && daysTimes_2.Length == 2) - { - int startWdIndex = (int)Enum.Parse(typeof(Weekdays), daysTimes_1[0]); - int endWdIndex = (int)Enum.Parse(typeof(Weekdays), daysTimes_2[0]); - - if (startWdIndex < endWdIndex) - { - _periodicsList.Add((Weekdays)startWdIndex + " " + daysTimes_1[1] + " to 23:59"); - - for (int i = startWdIndex+1; i <= endWdIndex-1; i++) - { - _periodicsList.Add((Weekdays)i + " 0:00 to 23:59"); - } - - _periodicsList.Add((Weekdays)endWdIndex + " 0:00 to " + daysTimes_2[1]); - } - else - { - int firstWdIndex = (int)Enum.GetValues(typeof(Weekdays)).Cast().First(); - int lastWdIndex = (int)Enum.GetValues(typeof(Weekdays)).Cast().Last(); - - _periodicsList.Add((Weekdays)startWdIndex + " " + daysTimes_1[1] + " to 23:59"); - - for (int i = startWdIndex + 1; i <= lastWdIndex; i++) - { - _periodicsList.Add((Weekdays)i + " 0:00 to 23:59"); - } - - for (int i = firstWdIndex; i <= endWdIndex-1; i++) - { - _periodicsList.Add((Weekdays)i + " 0:00 to 23:59"); - } - - _periodicsList.Add((Weekdays)endWdIndex + " 0:00 to " + daysTimes_2[1]); - } - } - else - { - _periodicsList.Add(period); - } - } - } - } - } - - public class Cisco_Interface : CiscoCommand - { - public string InterfaceName { get; set; } - public int SecurityLevel { get; set; } - public string VLan { get; set; } - public string IpAddress { get; set; } - public string Netmask { get; set; } - public bool Shutdown { get; set; } - public bool ManagementOnly { get; set; } - public bool LeadsToInternet { get; set; } - - public class Subnet - { - public string Network { get; private set; } - public string Netmask { get; private set; } - - public Subnet (string sIp, string sMask) - { - Network = sIp; - Netmask = sMask; - } - } - - public List Topology = new List(); - - public override string Name() { return "interface"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - InterfaceName = command.GetParam(1); - SecurityLevel = 0; - VLan = ""; - IpAddress = ""; - Netmask = ""; - Shutdown = false; - ManagementOnly = false; - LeadsToInternet = false; - - if (command.Children == null) - { - return; - } - - foreach (CiscoCommand child in command.Children) - { - switch (child.Name()) - { - case "security-level": - int securityLevel; - if (int.TryParse(((Cisco_SecurityLevel)child).Value, out securityLevel)) - { - SecurityLevel = securityLevel; - } - break; - - case "nameif": - CiscoId = ((Cisco_NameIf)child).Value; - break; - - case "vlan": - VLan = ((Cisco_VLan)child).Value; - break; - - case "shutdown": - Shutdown = ((Cisco_Shutdown)child).IsShutdown; - break; - - case "management-only": - ManagementOnly = ((Cisco_ManagementOnly)child).IsManagementOnly; - break; - - case "ip address": - IpAddress = ((Cisco_IP)child).IpAddress; - Netmask = ((Cisco_IP)child).Netmask; - - if (NetworkUtils.IsValidIp(IpAddress) && NetworkUtils.IsValidNetmask(Netmask)) - { - Topology.Add(new Subnet(NetworkUtils.GetNetwork(IpAddress, Netmask), Netmask)); - } - else - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid IP subnet (" + IpAddress + "/" + Netmask + ")."; - Console.WriteLine(ConversionIncidentMessage); - } - break; - } - } - } - - public bool HasValidIpAddress() - { - return NetworkUtils.IsValidIp(IpAddress) && NetworkUtils.IsValidNetmask(Netmask); - } - } - - public class Cisco_Route : CiscoCommand - { - public string InterfaceName { get; set; } - public bool DefaultRoute { get; set; } - public string DestinationIp { get; set; } - public string DestinationNetmask { get; set; } - public string Gateway { get; set; } - - public override string Name() { return "route"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - DefaultRoute = false; - InterfaceName = command.GetParam(1); - DestinationIp = command.GetParam(2); - DestinationNetmask = command.GetParam(3); - Gateway = command.GetParam(4); - - bool destinationIpResolved = false; - - if (ciscoIds.ContainsKey(DestinationIp)) - { - var refObj = (Cisco_Object)ciscoIds[DestinationIp]; - if (refObj != null) - { - switch (refObj.ObjectType) - { - case Cisco_Object.ObjectTypes.Host: - DestinationIp = refObj.HostAddress; - destinationIpResolved = true; - break; - - case Cisco_Object.ObjectTypes.Network: - DestinationIp = refObj.Network; - destinationIpResolved = true; - break; - } - } - } - else - { - DestinationIp = aliases.ContainsKey(DestinationIp) ? aliases[DestinationIp] : DestinationIp; - destinationIpResolved = true; - } - - if (!destinationIpResolved) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Cannot resolve route destination IP address (" + command.GetParam(2) + "). Using IP 1.1.1.1."; - Console.WriteLine(ConversionIncidentMessage); - - DestinationIp = "1.1.1.1"; - DestinationNetmask = "255.255.255.255"; - } - - if (!NetworkUtils.IsValidIp(DestinationIp)) - { - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Invalid IP address (" + DestinationIp + "). Using IP 1.1.1.1."; - Console.WriteLine(ConversionIncidentMessage); - - DestinationIp = "1.1.1.1"; - DestinationNetmask = "255.255.255.255"; - } - - if (DestinationIp == "0.0.0.0" && DestinationNetmask == "0.0.0.0") - { - DefaultRoute = true; - } - } - } - - public class Cisco_AntiSpoofing : CiscoCommand - { - public string InterfaceName { get; set; } - - public override string Name() { return "ip verify reverse-path interface"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - if (command.GetParam(1) == "verify" && command.GetParam(2) == "reverse-path" && command.GetParam(3) == "interface") - { - InterfaceName = command.GetParam(4); - } - } - } - - public class Cisco_SameSecurityTraffic : CiscoCommand - { - public enum InterfaceTrafficType { NA, Inter, Intra }; - - public InterfaceTrafficType TrafficType { get; set; } - - public override string Name() { return "same-security-traffic"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - if (command.GetParam(1) == "permit") - { - switch (command.GetParam(2)) - { - case "inter-interface": - TrafficType = InterfaceTrafficType.Inter; - break; - - case "intra-interface": - TrafficType = InterfaceTrafficType.Intra; - break; - } - } - } - } - - public class Cisco_Nat : CiscoCommand - { - public bool Inactive { get; set; } - public string RealInterface { get; set; } - public string MappedInterface { get; set; } - public bool IsStatic { get; set; } - public bool IsHideBehindInterface { get; set; } - public bool IsUnidirectional { get; set; } - public bool IsAutoAfter { get; set; } - public string StaticNatIpAddressOrObjectName { get; set; } - public string DynamicNatIpAddressOrObjectName { get; set; } - public string SourceId { get; set; } - public string TranslatedSourceId { get; set; } - public string DestinationId { get; set; } - public string TranslatedDestinationId { get; set; } - public string ServiceProtocol { get; set; } - public string ServiceId { get; set; } - public string TranslatedServiceId { get; set; } - - public override string Name() { return "nat"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - /************************************************************************************** - * There are two types of NAT: - * 1. Object NAT - child object of a Network Object - this is the commonly used NAT - * 2. Regular NAT - twice or manual NAT rule - more scalable, enables extra features over Object NAT - * - * Each of these two types may be Static or Dynamic. - * Static NAT allows bidirectional traffic (mirrored rules). - * - * Each NAT command is started as follows: - * --------------------------------------- - * nat [(real_interface, mapped_interface)] ... - * - **************************************************************************************/ - - base.Parse(command, prevCommand, ciscoIds, aliases); - - string param = command.GetParam(1).Trim(new char[] { '(', ')' }); - string[] interfaces = param.Split(','); - - if (interfaces.Length > 0) - { - RealInterface = interfaces[0]; - MappedInterface = (interfaces.Length > 1) ? interfaces[1] : ""; - } - else - { - RealInterface = ""; - MappedInterface = ""; - } - - Inactive = false; - IsStatic = false; - IsHideBehindInterface = false; - IsUnidirectional = false; - StaticNatIpAddressOrObjectName = ""; - DynamicNatIpAddressOrObjectName = ""; - SourceId = ""; - TranslatedSourceId = ""; - DestinationId = ""; - TranslatedDestinationId = ""; - ServiceProtocol = ""; - ServiceId = ""; - TranslatedServiceId = ""; - - if (command.IndentationLevel > 0) - { - ParseObjectNatCommand(command, prevCommand, ciscoIds); - } - else - { - ParseRegularNatCommand(command, prevCommand, ciscoIds); - } - - if (command.GetParamPosition("unidirectional") > 0/* || command.GetParamPosition("no-proxy-arp") > 0*/) // commented due to A.R. suggestion... - { - IsUnidirectional = true; - } - - if (command.GetParamPosition("inactive") > 0) - { - Inactive = true; - } - } - - private void ParseObjectNatCommand(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds) - { - /******************************************************** - * Parsing options for Object NAT: - * ------------------------------- - * ... static {mapped_host_ip_address | mapped_object_name | interface} [service {tcp | udp} real_port mapped_port] - * - * ... dynamic {mapped_host_ip_address | mapped_object_name | interface} - * - * + mapped_object may be a host or network or range - */ - - switch (command.GetParam(2)) - { - case "static": - IsStatic = true; - - if (command.GetParam(3) == "interface") - { - IsHideBehindInterface = true; // Static NAT with port-translation - } - else - { - // static hide behind an arbitrary ip/network - StaticNatIpAddressOrObjectName = command.GetParam(3); - } - - int servicePos = command.GetParamPosition("service"); - if (servicePos > 0) - { - ServiceProtocol = command.GetParam(servicePos + 1); - if (ServiceProtocol == "tcp" || ServiceProtocol == "udp") - { - ServiceId = CiscoKnownServices.ConvertServiceToPort(command.GetParam(servicePos + 2)); - TranslatedServiceId = CiscoKnownServices.ConvertServiceToPort(command.GetParam(servicePos + 3)); - } - else - { - ServiceProtocol = ""; - - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Unrecognized service protocol (" + ServiceProtocol + ")"; - Console.WriteLine(ConversionIncidentMessage); - } - } - break; - - case "dynamic": - if (command.GetParam(3) == "interface") - { - IsHideBehindInterface = true; - } - else - { - // dynamic hide behind an arbitrary ip/network - DynamicNatIpAddressOrObjectName = command.GetParam(3); - } - - // Check for interface fall-back configuration - if (command.GetParam(4) == "interface") - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Interface fall-back for dynamic object NAT is not supported"; - Console.WriteLine(ConversionIncidentMessage); - } - break; - } - } - - private void ParseRegularNatCommand(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds) - { - /******************************************************** - * Parsing options for regular (manual or twice) NAT: - * -------------------------------------------------- - * ... [after-object] source static real_object_name [mapped_object_name | interface] [destination static mapped_object_name real_object_name] [service real_service_name mapped_service_name] - * - * ... [after-auto] source dynamic {real_object_name | any} {mapped_object_name | interface} [destination static mapped_object_name real_object_name] [service mapped_service_name real_service_name] - * - * + real_object/mapped_object may be a host or network - */ - - int sourcePos = 2; - - if (command.GetParam(2) == "after-auto" || command.GetParam(2) == "after-object") - { - IsAutoAfter = true; - sourcePos = 3; - } - - if (command.GetParam(sourcePos) == "source") - { - if (command.GetParam(sourcePos + 1) == "static") - { - IsStatic = true; - } - - SourceId = command.GetParam(sourcePos + 2); - TranslatedSourceId = command.GetParam(sourcePos + 3); - if (TranslatedSourceId == "interface") - { - IsHideBehindInterface = true; - } - - int destPos = command.GetParamPosition("destination"); - if (destPos > 0) // twice-NAT - { - // check sanity - if (command.GetParam(destPos + 1) != "static") - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Not handling NAT with dynamic destination"; - Console.WriteLine(ConversionIncidentMessage); - return; - } - - DestinationId = command.GetParam(destPos + 2); - TranslatedDestinationId = command.GetParam(destPos + 3); - } - - int servicePos = command.GetParamPosition("service"); - if (servicePos > 0) - { - ServiceId = command.GetParam(servicePos + 1); - TranslatedServiceId = command.GetParam(servicePos + 2); - } - } - else - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Not handling NAT with dynamic source"; - Console.WriteLine(ConversionIncidentMessage); - } - } - } - - public class Cisco_AccessGroup : CiscoCommand - { - public enum DirectionType { Inbound, Outbound, Global }; - - public DirectionType Direction { get; set; } - public string AccessListName { get; set; } - public string InterfaceName { get; set; } - - public override string Name() { return "access-group"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - // Parsing Options: - //----------------- - // access-group access_list_name {{in | out} interface interface_name | global} - //----------------- - - base.Parse(command, prevCommand, ciscoIds, aliases); - - AccessListName = command.GetParam(1); - InterfaceName = (command.GetParam(3) == "interface") ? command.GetParam(4) : ""; - - switch (command.GetParam(2)) - { - case "in": - Direction = DirectionType.Inbound; - break; - - case "out": - Direction = DirectionType.Outbound; - break; - - case "global": - Direction = DirectionType.Global; - break; - - default: - Console.WriteLine("Error: unknown access-group traffic direction (" + command.GetParam(2) + ")."); - break; - } - - if (Direction != DirectionType.Inbound && Direction != DirectionType.Global) - { - ConversionIncidentType = ConversionIncidentType.Informative; - ConversionIncidentMessage = "Outbound ACLs will not be converted"; - Console.WriteLine(ConversionIncidentMessage); - } - } - } - - public class Cisco_AccessList : CiscoCommand - { - public enum ActionType { NA, Deny, Permit }; - - public class SourceDest - { - public enum SourceDestType { NA, Any, Any6, ReferenceObject, Host, SubnetAndMask }; - - public SourceDestType Type { get; set; } - public string HostIp { get; set; } - public string Subnet { get; set; } - public string Netmask { get; set; } - public string RefObjectName { get; set; } - public int WordsCount { get; set; } - - public SourceDest() - { - Type = SourceDestType.NA; - HostIp = ""; - Subnet = ""; - Netmask = ""; - RefObjectName = ""; - WordsCount = -1; - } - - public SourceDest(List words) : this() - { - if (!words.Any()) - { - WordsCount = 0; - return; - } - - switch (words[0]) - { - case "any": - case "any4": - Type = SourceDestType.Any; - WordsCount = 1; - break; - - case "any6": - Type = SourceDestType.Any6; - WordsCount = 1; - break; - - case "host": - Type = SourceDestType.Host; - if (words.Count > 1) - { - HostIp = words[1]; - WordsCount = 2; - } - break; - - case "object-group": - case "object": - Type = SourceDestType.ReferenceObject; - if (words.Count > 1) - { - RefObjectName = words[1]; - WordsCount = 2; - } - break; - - case "interface": - Type = SourceDestType.ReferenceObject; - if (words.Count > 1) - { - RefObjectName = InterfacePrefix + words[1]; - WordsCount = 2; - } - break; - - default: - // both the ip_address and ip_mask are specified - Type = SourceDestType.SubnetAndMask; - if (words.Count > 1) - { - Subnet = words[0]; - Netmask = words[1]; - WordsCount = 2; - } - break; - } - } - } - - public class ProtocolProperties - { - private Dictionary _ciscoIds; - - public ProtocolType Protocol { get; set; } - public TcpUdpPortOperatorType TcpUdpPortOperator { get; set; } - public ServiceDirection Where { get; set; } - public string TcpUdpPortValue { get; set; } - public int WordsCount { get; set; } - - public ProtocolProperties() - { - Protocol = ProtocolType.NA; - TcpUdpPortOperator = TcpUdpPortOperatorType.NA; - Where = ServiceDirection.Destination; - TcpUdpPortValue = ""; - WordsCount = -1; - } - - public ProtocolProperties(ProtocolType protocol, List words, Dictionary ciscoIds, ServiceDirection where) : this() - { - _ciscoIds = ciscoIds; - Protocol = protocol; - Where = where; - WordsCount = 0; - - if (protocol == ProtocolType.Ip || - protocol == ProtocolType.Tcp || - protocol == ProtocolType.Udp || - protocol == ProtocolType.ReferenceObject) - { - TcpUdpPortOperator = TcpUdpPortOperatorType.All; - - if (words.Count > 0) - { - switch (words[0]) - { - case "range": - TcpUdpPortOperator = TcpUdpPortOperatorType.Range; - if (words.Count > 2) - { - TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]) + "-" + - CiscoKnownServices.ConvertServiceToPort(words[2]); - WordsCount = 3; - } - break; - - case "lt": - TcpUdpPortOperator = TcpUdpPortOperatorType.Lt; - if (words.Count > 1) - { - TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); - WordsCount = 2; - } - break; - - case "gt": - TcpUdpPortOperator = TcpUdpPortOperatorType.Gt; - if (words.Count > 1) - { - TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); - WordsCount = 2; - } - break; - - case "eq": - TcpUdpPortOperator = TcpUdpPortOperatorType.Eq; - if (words.Count > 1) - { - TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); - WordsCount = 2; - } - break; - - case "neq": - TcpUdpPortOperator = TcpUdpPortOperatorType.Neq; - if (words.Count > 1) - { - TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); - WordsCount = 2; - } - break; - - - case "object": - if (words.Count > 1 && IsServiceObject(words[1])) - { - TcpUdpPortOperator = TcpUdpPortOperatorType.ReferenceObject; - TcpUdpPortValue = words[1]; - WordsCount = 2; - } - break; - - case "object-group": - if (words.Count > 1 && IsServiceGroup(words[1])) - { - TcpUdpPortOperator = TcpUdpPortOperatorType.ReferenceObject; - TcpUdpPortValue = words[1]; - WordsCount = 2; - } - break; - } - } - } - else if (protocol == ProtocolType.Icmp) - { - if (words.Count > 0) - { - switch (words[0]) - { - case "object-group": - if (words.Count > 1 && IsServiceGroup(words[1])) - { - TcpUdpPortOperator = TcpUdpPortOperatorType.ReferenceObject; - TcpUdpPortValue = words[1]; - WordsCount = 2; - } - break; - - default: - if (CiscoKnownServices.IsKnownIcmpService(words[0])) - { - TcpUdpPortOperator = TcpUdpPortOperatorType.Eq; - TcpUdpPortValue = CiscoKnownServices.ConvertIcmpServiceToType(words[0]); - WordsCount = 1; - } - break; - } - } - } - else if (protocol == ProtocolType.KnownOtherIpProtocol) - { - } - } - - private bool IsServiceGroup(string name) - { - if (_ciscoIds.ContainsKey(name) && _ciscoIds[name].Name() == "object-group") - { - var group = (Cisco_GroupObject)_ciscoIds[name]; - if (group.GroupType == Cisco_GroupObject.Group_Type.Service || group.GroupType == Cisco_GroupObject.Group_Type.Icmp) - { - return true; - } - } - - return false; - } - - private bool IsServiceObject(string name) - { - if (_ciscoIds.ContainsKey(name) && _ciscoIds[name].Name() == "object") - { - var obj = (Cisco_Object)_ciscoIds[name]; - if (obj.ObjectType == Cisco_Object.ObjectTypes.TcpService || - obj.ObjectType == Cisco_Object.ObjectTypes.UdpService || - obj.ObjectType == Cisco_Object.ObjectTypes.IcmpService) - { - return true; - } - } - - return false; - } - } - - public string ACLName { get; set; } - public bool Inactive { get; set; } - public ActionType Action { get; set; } - public ProtocolType Protocol { get; set; } - public string ProtocolReference { get; set; } - public string Remark { get; set; } - public bool IsRemark { get; set; } - public bool IsTimeRangeSpecified { get; set; } - public string TimeRangeName { get; set; } - public SourceDest Source { get; set; } - public SourceDest Destination { get; set; } - public ProtocolProperties SourceProperties { get; set; } - public ProtocolProperties DestinationProperties { get; set; } - - public override string Name() { return "access-list"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - /* - * OPTION I - REMARK format - the easiest option: - * - access-list access_list_name remark text - Example: - hostname(config)# access-list ACL_OUT remark - this is the inside admin address - * - * OPTION II - STANDARD format - used for a limited number of features, such as route maps or VPN filters. - * uses IPv4 addresses only, and defines destination addresses only. - * - access-list access_list_name standard {deny | permit} {any/any4 | host ip_address | ip_address ip_mask} - Example: - hostname(config)# access-list OSPF standard permit 192.168.1.0 255.255.255.0 - * - * OPTION III.I - EXTENDED format - for ICMP based traffic matching - * - access-list access_list_name extended {deny | permit} icmp source_address_argument dest_address_argument [icmp_argument] [time-range time_range_name] [inactive] - Example: - hostname(config)# access-list ACL_IN extended permit icmp any any echo - * - * OPTION III.II - EXTENDED format - for TCP and UDP based traffic matching, with ports - * - access-list access_list_name extended {deny | permit} {tcp | udp} source_address_argument [port_argument] dest_address_argument [port_argument] [time-range time_range_name] [inactive] - Example: - hostname(config)# access-list ACL_IN extended deny tcp any host 209.165.201.29 eq www - hostname(config)# access-list ACL_IN extended deny tcp 192.168.1.0 255.255.255.0 209.165.201.0 255.255.255.224 - * - * OPTION III.III - EXTENDED format - for general IP address and FQDN based matching - * - access-list access_list_name extended {deny | permit} protocol_argument source_address_argument dest_address_argument [time-range time_range_name] [inactive] - Example: - hostname(config)# access-list ACL_IN extended permit ip any any - * - * ********************** - * ACL COMMAND ARGUMENTS: - * - * protocol_argument specification: one of the following options: - * -------------------------------------------------------------- - * protocol_name/protocol_number - * object service_object_id --> may be also a icmp service object - * object-group service_group_id - * object-group protocol_group_id - * - * source_address_argument/dest_address_argument specification: one of the following options: - * ------------------------------------------------------------------------------------------ - * any/any4/any6 - * host ip_address - * interface interface_name - * object network_object_id - * object-group network_group_id - * ip_address ip_mask - * - * icmp_argument specification: one of the following options: - * ---------------------------------------------------------- - * icmp_type - * object-group icmp_group_id --> object-group icmp-type command - * - * port_argument specification: one of the following options: - * ---------------------------------------------------------- - * operator port --> where operator can be one of: lt, gt, eq, neq, range; port can be number or name of a TCP or UDP port - * object-group service_group_id - * - */ - - base.Parse(command, prevCommand, ciscoIds, aliases); - - ACLName = command.GetParam(1); - Inactive = false; - Action = ActionType.NA; - Protocol = ProtocolType.NA; - ProtocolReference = ""; - Remark = ""; - IsRemark = false; - IsTimeRangeSpecified = false; - - var prevAclCommand = prevCommand as Cisco_AccessList; - - if (command.GetParam(2) == "remark") - { - IsRemark = true; - - // Note that there may be several consecutive remark lines, so we need to aggregate to a single remark - string dataForNextElement = ""; - if (prevAclCommand != null && prevAclCommand.IsRemark && !string.IsNullOrEmpty(prevAclCommand.DataForNextElement)) - { - dataForNextElement = prevAclCommand.DataForNextElement; - } - - string text = command.Text.Trim(); - int offset = text.IndexOf("remark") + 7; - - if (!string.IsNullOrEmpty(dataForNextElement)) - { - dataForNextElement += ", "; - } - - dataForNextElement += text.Substring(offset).Trim(); - DataForNextElement = dataForNextElement; - - return; - } - - if (prevAclCommand != null && ACLName.Equals(prevAclCommand.ACLName) && !string.IsNullOrEmpty(prevAclCommand.DataForNextElement)) - { - Remark = prevAclCommand.DataForNextElement; - - if (CiscoParser.SpreadAclRemarks) - { - DataForNextElement = Remark; - } - } - - int denyPosition = command.GetParamPosition("deny"); - int permitPosition = command.GetParamPosition("permit"); - int protocolPosition = Math.Max(denyPosition, permitPosition) + 1; // protocol field should follow the action field (either deny or permit) - int sourcePosition = protocolPosition + 1; - - if (denyPosition > 0) - { - Action = ActionType.Deny; - } - - if (permitPosition > 0) - { - Action = ActionType.Permit; - } - - if (command.GetParam(2) == "standard") - { - Protocol = ProtocolType.Ip; - - Source = new SourceDest - { - Type = SourceDest.SourceDestType.Any - }; - - SourceProperties = new ProtocolProperties - { - Protocol = Protocol, - TcpUdpPortOperator = TcpUdpPortOperatorType.All - }; - - Destination = new SourceDest(command.GetParams(4)); - - DestinationProperties = new ProtocolProperties - { - Protocol = Protocol, - TcpUdpPortOperator = TcpUdpPortOperatorType.All - }; - - return; - } - - if (command.GetParamPosition("time-range") > 0) - { - IsTimeRangeSpecified = true; - int indexTimeRange = command.GetParamPosition("time-range"); - TimeRangeName = command.GetParam(indexTimeRange + 1); - } - - if (command.GetParamPosition("inactive") > 0) - { - Inactive = true; - } - - string strProtocol = command.GetParam(protocolPosition); - switch (strProtocol) - { - case "ip": - Protocol = ProtocolType.Ip; - break; - - case "icmp": - case "icmp6": - Protocol = ProtocolType.Icmp; - break; - - case "udp": - Protocol = ProtocolType.Udp; - break; - - case "tcp": - Protocol = ProtocolType.Tcp; - break; - - case "object-group": - case "object": - Protocol = ProtocolType.ReferenceObject; - ProtocolReference = command.GetParam(protocolPosition + 1); - sourcePosition++; - break; - - default: - string serviceName; - if (CiscoKnownServices.IsKnownService(strProtocol)) - { - Protocol = ProtocolType.KnownOtherIpProtocol; - } - else if (CiscoKnownServices.IsKnownServiceNumber(strProtocol, out serviceName)) // protocol number is used!!! - { - Protocol = ProtocolType.KnownOtherIpProtocol; - strProtocol = serviceName; - } - else - { - ProtocolReference = strProtocol; - ConversionIncidentType = ConversionIncidentType.ManualActionRequired; - ConversionIncidentMessage = "Unrecognized service protocol (" + strProtocol + ")"; - Console.WriteLine(ConversionIncidentMessage); - } - break; - } - - Source = new SourceDest(command.GetParams(sourcePosition)); - SourceProperties = new ProtocolProperties(Protocol, command.GetParams(sourcePosition + Source.WordsCount), ciscoIds, ServiceDirection.Source); - Destination = new SourceDest(command.GetParams(sourcePosition + Source.WordsCount + SourceProperties.WordsCount)); - DestinationProperties = new ProtocolProperties(Protocol, command.GetParams(sourcePosition + Source.WordsCount + SourceProperties.WordsCount + Destination.WordsCount), ciscoIds, ServiceDirection.Destination); - - if (Protocol == ProtocolType.KnownOtherIpProtocol) - { - // This information is needed in order to create/query appropriate service objects - DestinationProperties.TcpUdpPortValue = strProtocol; - DestinationProperties.WordsCount = 1; - } - } - } - - public class Cisco_ClassMap : CiscoCommand - { - public string ClassMapName; - public List MatchedAclNames = new List(); - - public override string Name() { return "class-map"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - base.Parse(command, prevCommand, ciscoIds, aliases); - - ClassMapName = command.GetParam(1); - - if (command.Children == null) - { - return; - } - - foreach (CiscoCommand child in command.Children) - { - if (child.Name() == "match" && !string.IsNullOrEmpty(((Cisco_Match_AccessList)child).AccessListName)) - { - MatchedAclNames.Add(((Cisco_Match_AccessList)child).AccessListName); - } - } - } - } - - public class Cisco_Match_AccessList : CiscoCommand - { - public string AccessListName { get; set; } - - public override string Name() { return "match"; } - - public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) - { - // Parsing Options: - //----------------- - // match access-list access_list_name - //----------------- - - base.Parse(command, prevCommand, ciscoIds, aliases); - - AccessListName = (command.GetParam(1) == "access-list") ? command.GetParam(2) : ""; - } - } -} +/******************************************************************** +Copyright (c) 2017, Check Point Software Technologies Ltd. +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. +********************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using CommonUtils; + +namespace CiscoMigration +{ + public enum ProtocolType { NA, Ip, Icmp, Udp, Tcp, KnownOtherIpProtocol, ReferenceObject, Icmp6 }; + public enum TcpUdpPortOperatorType { NA, All, Lt, Gt, Eq, Neq, Range, ReferenceObject }; + public enum ServiceDirection { Source, Destination }; + + public interface ICiscoCommand + { + string Name(); + void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases); + } + + /// + /// Represents a basic Cisco command. + /// Each derived command auto-parses the appropriate configuration line text according to its "name" (via reflection mechanism). + /// Some commands may have child commands (network group commad has child network object commands). + /// The "Id" property is the configuration line number. + /// The "ParentId" property is the parent configuration line number. + /// The "CiscoId" property is the user defined name of the command. + /// + public class CiscoCommand : ICiscoCommand + { + public const string InterfacePrefix = "Interface_"; + public const string Any = "any"; + + private string _text = ""; + private string[] _words; + + public string Text + { + get { return _text; } + set + { + _text = value; + + string trimmedText = _text.Trim(); + char[] delimiterChars = { ' ', '\t' }; + + // Replace multiple spaces with a single space + trimmedText = Regex.Replace(trimmedText, @"\s+", " "); + + _words = trimmedText.Split(delimiterChars); + } + } + + public int IndentationLevel + { + get + { + if (Text.Length == 0) + { + return 0; + } + + int pos = 0; + while (Text.Substring(pos, 1) == " ") + { + pos++; + } + return pos; + } + } + + public string FirstWord + { + get + { + if (_words != null && _words.Any()) + { + // This is a special handling!!! + // There are several commands that have the first word "ip"... + if (_words[0] == "ip") + { + if (_words.Count() > 1 && _words[1] == "address") + { + return _words[0] + " " + _words[1]; + } + if (_words.Count() > 3 && _words[1] == "verify" && _words[2] == "reverse-path" && _words[3] == "interface") + { + return _words[0] + " " + _words[1] + " " + _words[2] + " " + _words[3]; + } + } + else + { + return _words[0]; + } + } + + return ""; + } + } + + public int Id { get; set; } + public int? ParentId { get; set; } + public string CiscoId { get; set; } + public string Description { get; set; } + public string Tag { get; set; } + public string DataForNextElement { get; set; } + public bool KnownCommand { get; set; } + public bool NotAnInterestingCommand { get; set; } + public ConversionIncidentType ConversionIncidentType { get; set; } + public string ConversionIncidentMessage { get; set; } + public List Children { get; set; } + + public CiscoCommand() + { + CiscoId = ""; + Description = ""; + DataForNextElement = ""; + } + + public string GetParam(int pos) + { + if (_words == null || _words.Length <= pos) + { + return ""; + } + + return _words[pos]; + } + + public List GetParams(int pos) + { + var res = new List(); + + if (_words == null || !_words.Any()) + { + return res; + } + + for (int i = 0; i < _words.Length; i++) + { + if (i >= pos) + { + res.Add(_words[i]); + } + } + + return res; + } + + public int GetParamPosition(string paramName) + { + if (_words == null || !_words.Any()) + { + return -1; + } + + int pos = 0; + foreach (string word in _words) + { + if (word == paramName) + { + return pos; + } + pos++; + } + + return -1; + } + + public List Flatten() + { + var res = new List(); + res.Add(this); + + if (Children != null) + { + foreach (CiscoCommand child in Children) + { + foreach (CiscoCommand flattenchild in child.Flatten()) + { + res.Add(flattenchild); + } + } + } + + return res; + } + + public virtual string Name() { return ""; } + + public virtual void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + if (command.Children != null) + { + foreach (CiscoCommand child in command.Children) + { + if (child.Name() == "description") + { + Description = child.Description; + } + } + } + + ConversionIncidentType = ConversionIncidentType.None; + ConversionIncidentMessage = ""; + } + } + + public class Cisco_Description : CiscoCommand + { + public Cisco_Description() + { + NotAnInterestingCommand = true; + } + + public override string Name() { return "description"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + if (!string.IsNullOrEmpty(command.Text)) + { + Description = command.Text.Trim().Substring(Name().Length + 1); + } + + } + } + + public class Cisco_ASA : CiscoCommand + { + public string Version { get; set; } + + public override string Name() { return "ASA"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + const string version = "version"; + if (!string.IsNullOrEmpty(command.Text) && command.GetParam(1).ToLower() == version) + { + Version = command.Text.Trim().Substring(Name().Length + version.Length + 2); + } + else + { + Version = ""; + } + } + } + + public class Cisco_Alias : CiscoCommand + { + public override string Name() { return "name"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + string real = command.GetParam(1); + string alias = command.GetParam(2); + + if (!string.IsNullOrEmpty(alias) && !string.IsNullOrEmpty(real) && !aliases.ContainsKey(alias)) + { + aliases.Add(alias, real); + } + } + } + + public class Cisco_SSH : CiscoCommand + { + public string IpAddress { get; set; } + public string Netmask { get; set; } + public string Interface { get; set; } + + public override string Name() { return "ssh"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + IpAddress = ""; + Netmask = ""; + Interface = ""; + + string commandParam = command.GetParam(1); + if (NetworkUtils.IsValidIp(commandParam)) + { + IpAddress = commandParam; + } + else + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "IPv4 address was expected, but '" + commandParam + "' was found."; + return; + } + + commandParam = command.GetParam(2); + if (NetworkUtils.IsValidNetmaskv4(commandParam)) + { + Netmask = commandParam; + } + else + { + IpAddress = ""; + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "IPv4 netmask was expected, but " + commandParam + " was found."; + return; + } + + Interface = command.GetParam(3); + } + } + + public class Cisco_Hostname : CiscoCommand + { + public string HostName { get; set; } + + public override string Name() { return "hostname"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + HostName = command.GetParam(1); + } + } + + public class Cisco_Object : CiscoCommand + { + public enum ObjectTypes { NA, Fqdn, Host, Network, Range, TcpService, UdpService, IcmpService, KnownOtherService, Icmp6Service }; + + public ObjectTypes ObjectType { get; set; } + public string Fqdn { get; set; } + public string HostAddress { get; set; } + public string Network { get; set; } + public string Netmask { get; set; } + public string MaskPrefix { get; set; } + public string RangeFrom { get; set; } + public string RangeTo { get; set; } + public bool IsDestination { get; set; } + public string ServiceProtocol { get; set; } + public string ServiceOperator { set; get; } + public string ServicePort { get; set; } + + public override string Name() { return "object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + CiscoId = command.GetParam(2); + ObjectType = ObjectTypes.NA; + + switch (command.GetParam(1)) + { + case "network": + ParseNetworks(); + break; + + case "service": + ParseServices(); + break; + + default: + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Unrecognized object type (" + command.GetParam(1) + ")"; + break; + } + } + + private void ParseNetworks() + { + if (Children == null) + { + return; + } + + int found = 0; + + foreach (CiscoCommand child in Children) + { + switch (child.Name()) + { + case "fqdn": + ObjectType = ObjectTypes.Fqdn; + Fqdn = ((Cisco_Fqdn)child).Fqdn; + found++; + break; + + case "host": + ObjectType = ObjectTypes.Host; + HostAddress = ((Cisco_Host)child).HostAddress; + found++; + break; + + case "subnet": + ObjectType = ObjectTypes.Network; + Network = ((Cisco_Subnet)child).Network; + Netmask = ((Cisco_Subnet)child).Netmask; + MaskPrefix = ((Cisco_Subnet)child).MaskPrefix; + found++; + break; + + case "range": + ObjectType = ObjectTypes.Range; + RangeFrom = ((Cisco_Range)child).RangeFrom; + RangeTo = ((Cisco_Range)child).RangeTo; + found++; + break; + } + + if (found == 1) + { + if (child.ConversionIncidentType != ConversionIncidentType.None) + { + ConversionIncidentType = child.ConversionIncidentType; + ConversionIncidentMessage = child.ConversionIncidentMessage; + } + } + } + + if (found > 1) + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "An Object (network) can only hold one fqdn, host, range or subnet"; + Console.WriteLine(ConversionIncidentMessage); + } + } + + private void ParseServices() + { + if (Children == null) + { + return; + } + + int found = 0; + + foreach (CiscoCommand child in Children) + { + if (child.Name() == "service") + { + found++; + + var service = (Cisco_Service)child; + ServiceProtocol = service.Protocol; + ServiceOperator = service.Operator; + ServicePort = service.Port; + IsDestination = service.IsDestination; + + if (service.ConversionIncidentType != ConversionIncidentType.None) + { + ConversionIncidentType = service.ConversionIncidentType; + ConversionIncidentMessage = service.ConversionIncidentMessage; + } + + switch (ServiceProtocol) + { + case "ip": + // Predefined "any" object. No special handling... + break; + + case "icmp": + ObjectType = ObjectTypes.IcmpService; + break; + + case "icmp6": + ObjectType = ObjectTypes.Icmp6Service; + break; + + case "tcp": + ObjectType = ObjectTypes.TcpService; + break; + + case "udp": + ObjectType = ObjectTypes.UdpService; + break; + + default: + // No need to check also for CiscoKnownServices.IsKnownServiceNumber here, + // because it is already done in Cisco_Service class!!! + if (CiscoKnownServices.IsKnownService(ServiceProtocol)) + { + ObjectType = ObjectTypes.KnownOtherService; + } + else + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Unrecognized service protocol (" + ServiceProtocol + ")"; + Console.WriteLine(ConversionIncidentMessage); + } + break; + } + } + } + + if (found > 1) + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "An Object (service) can only hold one service"; + Console.WriteLine(ConversionIncidentMessage); + } + } + } + + public class Cisco_Fqdn : CiscoCommand + { + public string Fqdn { get; set; } + + public override string Name() { return "fqdn"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + Fqdn = (command.GetParam(1) == "v4") ? command.GetParam(2) : command.GetParam(1); + } + } + + public class Cisco_Host : CiscoCommand + { + public string HostAddress { get; set; } + + public override string Name() { return "host"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + HostAddress = command.GetParam(1); + if (!NetworkUtils.IsValidIp(HostAddress)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid host IP address (" + HostAddress + "). Using IP 1.1.1.1."; + Console.WriteLine(ConversionIncidentMessage); + + HostAddress = "1.1.1.1"; + } + } + } + + public class Cisco_Subnet : CiscoCommand + { + public string Network { get; set; } + public string Netmask { get; set; } + public string MaskPrefix { get; set; } + + public override string Name() { return "subnet"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + Network = command.GetParam(1); + Netmask = command.GetParam(2); + string sNetwork; + string sMaskLength; + if (NetworkUtils.TryParseNetwortWithPrefix(Network, out sNetwork, out sMaskLength)) + { + Network = sNetwork; + MaskPrefix = sMaskLength; + } + else if (!NetworkUtils.IsValidIpv4(Network) || !NetworkUtils.IsValidNetmaskv4(Netmask)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid IP subnet (" + Network + "/" + Netmask + "). Using IP subnet 1.1.1.0/255.255.255.0."; + Console.WriteLine(ConversionIncidentMessage); + + Network = "1.1.1.0"; + Netmask = "255.255.255.0"; + } + } + } + + public class Cisco_Range : CiscoCommand + { + public string RangeFrom { get; set; } + public string RangeTo { get; set; } + + public override string Name() { return "range"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + RangeFrom = command.GetParam(1); + if (!NetworkUtils.IsValidIp(RangeFrom)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid range starting IP address (" + RangeFrom + "). Using IP 0.0.0.0."; + Console.WriteLine(ConversionIncidentMessage); + + RangeFrom = "0.0.0.0"; + } + + RangeTo = command.GetParam(2); + if (!NetworkUtils.IsValidIp(RangeTo)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid range ending IP address (" + RangeTo + "). Using IP 255.255.255.255."; + Console.WriteLine(ConversionIncidentMessage); + + RangeTo = "255.255.255.255"; + } + } + } + + public class Cisco_Service : CiscoCommand + { + public string Protocol { get; set; } + public bool IsDestination { get; set; } + public string Port { get; set; } + public string Operator { get; set; } + + public override string Name() { return "service"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + // Parsing Options: + //----------------- + // 1. service protocol_name_or_number + // 2. service {icmp | icmp6} [icmp-type] + // 3. service {tcp | udp} [source operator port] [destination operator port] + //----------------- + + Protocol = command.GetParam(1); + + IsDestination = false; + Port = ""; + Operator = ""; + + switch (Protocol) + { + case "ip": + IsDestination = true; + break; + + case "icmp": + IsDestination = true; + Protocol = "icmp"; + Operator = "eq"; + Port = CiscoKnownServices.ConvertIcmpServiceToType(command.GetParam(2)); + break; + + case "icmp6": + IsDestination = true; + Protocol = "icmp6"; + Operator = "eq"; + Port = CiscoKnownServices.ConvertIcmpServiceToType(command.GetParam(2)); + break; + + case "tcp": + case "udp": + IsDestination = (command.GetParam(2) == "destination"); + Operator = command.GetParam(3); + Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(4)); + + int nextParamId = 5; // we need this because of 'range' operator + + if (Operator == "range") + { + Operator = "eq"; + Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(5)); + nextParamId = 6; // !!! + } + + if (!IsDestination && command.GetParam(nextParamId) == "destination") + { + // "service tcp source eq ssh destination eq ssh" ---> wrong!!! ---> ignore source!!! + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Cannot convert a service defined as both source service and destination service. Ignoring source service."; + Console.WriteLine(ConversionIncidentMessage); + + IsDestination = true; + Operator = command.GetParam(nextParamId + 1); + Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 2)); + + if (Operator == "range") + { + Operator = "eq"; + Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 3)); + } + } + + if (string.IsNullOrEmpty(Operator) || string.IsNullOrEmpty(Port)) + { + // Use ALL tcp/udp ports if nothing specified!!! + IsDestination = true; + Operator = "all"; + Port = "1-65535"; + } + break; + + default: + IsDestination = true; + + string serviceName; + if (CiscoKnownServices.IsKnownService(Protocol)) + { + Port = CiscoKnownServices.ConvertServiceToPort(Protocol); + } + else if (CiscoKnownServices.IsKnownServiceNumber(Protocol, out serviceName)) // protocol number is used!!! + { + Port = Protocol; + Protocol = serviceName; + } + else + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Unrecognized service protocol (" + Protocol + ")"; + Console.WriteLine(ConversionIncidentMessage); + } + break; + } + } + } + + public class Cisco_NetworkObject : CiscoCommand + { + public string IpAddress { get; set; } + public string Netmask { get; set; } + public string MaskPrefix { get; set; } + public string ReferencedObject { get; set; } + + public override string Name() { return "network-object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + IpAddress = ""; + Netmask = ""; + ReferencedObject = ""; + + switch (command.GetParam(1)) + { + case "object": + ReferencedObject = command.GetParam(2); + break; + + case "host": + string ipAddressOrObjectName = command.GetParam(2); + if (ciscoIds.ContainsKey(ipAddressOrObjectName)) + { + ReferencedObject = ipAddressOrObjectName; + } + else + { + IpAddress = aliases.ContainsKey(ipAddressOrObjectName) ? aliases[ipAddressOrObjectName] : ipAddressOrObjectName; + if (!NetworkUtils.IsValidIp(IpAddress)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid IP address (" + IpAddress + "). Using IP 1.1.1.1."; + Console.WriteLine(ConversionIncidentMessage); + + IpAddress = "1.1.1.1"; + } + + Netmask = "255.255.255.255"; + } + break; + + default: + // subnet + IpAddress = command.GetParam(1); + if (aliases.ContainsKey((IpAddress))) + { + IpAddress = aliases[IpAddress]; + } + Netmask = command.GetParam(2); + + string sIp; + string sMaskLenth; + if (NetworkUtils.TryParseNetwortWithPrefix(IpAddress, out sIp, out sMaskLenth)) + { + IpAddress = sIp; + MaskPrefix = sMaskLenth; + } + else if (!NetworkUtils.IsValidIpv4(IpAddress) || !NetworkUtils.IsValidNetmaskv4(Netmask)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid IP subnet (" + IpAddress + "/" + Netmask + "). Using IP subnet 1.1.1.0/255.255.255.0."; + Console.WriteLine(ConversionIncidentMessage); + + IpAddress = "1.1.1.0"; + Netmask = "255.255.255.0"; + } + break; + } + } + } + + public class Cisco_ProtocolObject : CiscoCommand + { + public string ProtocolName { get; set; } + + public override string Name() { return "protocol-object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + ProtocolName = command.GetParam(1); + } + } + + public class Cisco_PortObject : CiscoCommand + { + public string Port { get; set; } + + public override string Name() { return "port-object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + Port = ""; + + string portOperator = command.GetParam(1); + + switch (portOperator) + { + case "eq": + Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(2)); + break; + + case "range": + Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(2)) + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(3)); + break; + } + } + } + + public class Cisco_ServiceObject : CiscoCommand + { + public string Protocol { get; set; } + public bool IsDestination { get; set; } + public string Port { get; set; } + public string Operator { get; set; } + public string RefObjectName { get; set; } + + public override string Name() { return "service-object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + // Parsing Options: + //----------------- + // 1. service-object object object_name + // 2. service-object protocol_name_or_number + // 3. service-object {icmp | icmp6} [icmp-type] + // 4. service-object {tcp | udp | tcp-udp} [source operator port] [destination operator port] + //----------------- + + Protocol = command.GetParam(1); + + IsDestination = false; + Port = ""; + Operator = ""; + RefObjectName = ""; + + switch (Protocol) + { + case "object": + RefObjectName = command.GetParam(2); + Protocol = ""; + break; + + case "ip": + IsDestination = true; + break; + + case "icmp": + IsDestination = true; + Protocol = "icmp"; + Operator = "eq"; + Port = CiscoKnownServices.ConvertIcmpServiceToType(command.GetParam(2)); + break; + + case "icmp6": + IsDestination = true; + Protocol = "icmp6"; + Operator = "eq"; + Port = CiscoKnownServices.ConvertIcmpServiceToType(command.GetParam(2)); + break; + + case "tcp": + case "udp": + case "tcp-udp": + IsDestination = (command.GetParam(2) == "destination"); + Operator = command.GetParam(3); + Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(4)); + + int nextParamId = 5; // we need this because of 'range' operator + + if (Operator == "range") + { + Operator = "eq"; + Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(5)); + nextParamId = 6; // !!! + } + + if (!IsDestination && command.GetParam(nextParamId) == "destination") + { + // "service-object tcp source eq ssh destination eq ssh" ---> wrong!!! ---> ignore source!!! + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Cannot convert a service defined as both source service and destination service. Ignoring source service."; + Console.WriteLine(ConversionIncidentMessage); + + IsDestination = true; + Operator = command.GetParam(nextParamId + 1); + Port = CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 2)); + + if (Operator == "range") + { + Operator = "eq"; + Port = Port + "-" + CiscoKnownServices.ConvertServiceToPort(command.GetParam(nextParamId + 3)); + } + } + + if (string.IsNullOrEmpty(Operator) || string.IsNullOrEmpty(Port)) + { + // Use ALL tcp/udp ports if nothing specified!!! + IsDestination = true; + Operator = "all"; + Port = "1-65535"; + } + break; + + default: + IsDestination = true; + + string serviceName; + if (CiscoKnownServices.IsKnownService(Protocol)) + { + Port = CiscoKnownServices.ConvertServiceToPort(Protocol); + } + else if (CiscoKnownServices.IsKnownServiceNumber(Protocol, out serviceName)) // protocol number is used!!! + { + Port = Protocol; + Protocol = serviceName; + } + else + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Unrecognized service protocol (" + Protocol + ")"; + Console.WriteLine(ConversionIncidentMessage); + } + break; + } + } + } + + public class Cisco_IcmpObject : CiscoCommand + { + public string IcmpType { get; set; } + + public override string Name() { return "icmp-object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + IcmpType = command.GetParam(1); + } + } + + public class Cisco_ReferenceGroupObject : CiscoCommand + { + public string ReferenceId { get; set; } + + public override string Name() { return "group-object"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + ReferenceId = command.GetParam(1); + } + } + + public class Cisco_GroupObject : CiscoCommand + { + public enum Group_Type { NA, Service, Protocol, Icmp, Network, Icmp6 }; + + private Dictionary _ciscoIds; + + public Group_Type GroupType { get; set; } + public string ServiceProtocol { get; set; } + + public List Protocols = new List(); + public List IcmpTypes = new List(); + public List MembersGroupNames = new List(); + public List MemberObjects = new List(); + + public override string Name() { return "object-group"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + _ciscoIds = ciscoIds; + + CiscoId = command.GetParam(2); + ServiceProtocol = ""; + + switch (command.GetParam(1)) + { + case "service": + GroupType = Group_Type.Service; + break; + + case "protocol": + GroupType = Group_Type.Protocol; + break; + + case "icmp-type": + GroupType = Group_Type.Icmp; + break; + + case "network": + GroupType = Group_Type.Network; + break; + + default: + GroupType = Group_Type.NA; + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Unrecognized group type (" + command.GetParam(1) + ")"; + return; + } + + if (GroupType == Group_Type.Service) + { + ServiceProtocol = command.GetParam(3); + } + + if (command.Children == null) + { + return; + } + + foreach (CiscoCommand child in command.Children) + { + bool hasValidChild = true; + + switch (child.Name()) + { + case "protocol-object": + Protocols.Add(((Cisco_ProtocolObject)child).ProtocolName); + break; + + case "port-object": + MemberObjects.Add((Cisco_PortObject)child); + break; + + case "icmp-object": + IcmpTypes.Add(((Cisco_IcmpObject)child).IcmpType); + break; + + case "group-object": + MembersGroupNames.Add(((Cisco_ReferenceGroupObject)child).ReferenceId); + break; + + case "network-object": + MemberObjects.Add((Cisco_NetworkObject)child); + break; + + case "service-object": + MemberObjects.Add((Cisco_ServiceObject)child); + break; + + default: + hasValidChild = false; + break; + } + + if (hasValidChild) + { + if (child.ConversionIncidentType != ConversionIncidentType.None) + { + ConversionIncidentType = child.ConversionIncidentType; + ConversionIncidentMessage = child.ConversionIncidentMessage; + } + } + } + } + + public List GetChildServices() + { + var services = new List(); + + if (Children != null) + { + foreach (CiscoCommand child in Children) + { + if (child.Name() == "service-object") + { + services.Add((Cisco_ServiceObject)child); + } + else if (child.Name() == "group-object") + { + if (_ciscoIds.ContainsKey(((Cisco_ReferenceGroupObject)child).ReferenceId)) + { + var referencedGroupObject = (Cisco_GroupObject)_ciscoIds[((Cisco_ReferenceGroupObject)child).ReferenceId]; + var referencedGroupServices = referencedGroupObject.GetChildServices(); + + foreach (Cisco_ServiceObject referencedService in referencedGroupServices) + { + if (!services.Contains(referencedService)) + { + services.Add(referencedService); + } + } + } + } + } + } + + return services; + } + + public List GetChildPorts() + { + var ports = new List(); + + if (Children != null) + { + foreach (CiscoCommand child in Children) + { + if (child.Name() == "port-object") + { + ports.Add((Cisco_PortObject)child); + } + else if (child.Name() == "group-object") + { + if (_ciscoIds.ContainsKey(((Cisco_ReferenceGroupObject)child).ReferenceId)) + { + var referencedGroupObject = (Cisco_GroupObject)_ciscoIds[((Cisco_ReferenceGroupObject)child).ReferenceId]; + var referencedGroupPorts = referencedGroupObject.GetChildPorts(); + + foreach (Cisco_PortObject referencedPort in referencedGroupPorts) + { + if (!ports.Contains(referencedPort)) + { + ports.Add(referencedPort); + } + } + } + } + } + } + + return ports; + } + } + + public class Cisco_SecurityLevel : CiscoCommand + { + public string Value { get; set; } + + public override string Name() { return "security-level"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + Value = command.GetParam(1); + } + } + + public class Cisco_NameIf : CiscoCommand + { + public string Value { get; set; } + + public override string Name() { return "nameif"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + Value = InterfacePrefix + command.GetParam(1); + } + } + + public class Cisco_VLan : CiscoCommand + { + public string Value { get; set; } + + public override string Name() { return "vlan"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + Value = command.GetParam(1); + } + } + + public class Cisco_IP : CiscoCommand + { + public string IpAddress { get; set; } + public string Netmask { get; set; } + + public override string Name() { return "ip address"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + IpAddress = ""; + Netmask = ""; + + if (command.GetParam(1) == "address") + { + IpAddress = command.GetParam(2); + Netmask = command.GetParam(3); + } + } + } + + public class Cisco_Shutdown : CiscoCommand + { + public bool IsShutdown { get; set; } + + public override string Name() { return "shutdown"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + IsShutdown = (command.GetParam(0) == "shutdown"); + } + } + + public class Cisco_ManagementOnly : CiscoCommand + { + public bool IsManagementOnly { get; set; } + + public override string Name() { return "management-only"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + IsManagementOnly = (command.GetParam(0) == "management-only"); + } + } + + public class Cisco_TimeRange : CiscoCommand + { + public enum Weekdays { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; + + private string _timeRangeName; + + private string _startDateTime; + private string _endDateTime; + + private List _periodicsList; + + public string TimeRangeName + { + get { return _timeRangeName; } + } + + public string StartDateTime + { + get { return _startDateTime; } + } + + public string EndDateTime + { + get { return _endDateTime; } + } + + public List PeriodicsList + { + get { return _periodicsList; } + } + + public override string Name() { return "time-range"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + _periodicsList = new List(); + + _timeRangeName = this.GetParam(1); + + foreach (CiscoCommand child in Children) + { + if (child.FirstWord.Equals("absolute")) + { + int startIndex = child.Text.IndexOf("start"); + int endIndex = child.Text.IndexOf("end"); + if (startIndex > -1 && endIndex > -1) + { + _startDateTime = child.Text.Substring("absolute".Length + "start".Length + 2, endIndex - startIndex - "start".Length).Trim(); + _endDateTime = child.Text.Substring(endIndex + "end".Length).Trim(); + } + else if (startIndex > -1 && endIndex == -1) + { + _startDateTime = child.Text.Substring("absolute".Length + "start".Length + 2).Trim(); + } + else if (startIndex == -1 && endIndex > -1) + { + _endDateTime = child.Text.Substring("absolute".Length + "end".Length + 2).Trim(); + } + } + + if (child.FirstWord.Equals("periodic")) + { + string period = child.Text.Substring("periodic".Length + 1).Trim(); + + string[] daysTimes = period.Trim().Split(new string[] { "to" }, StringSplitOptions.RemoveEmptyEntries); + + string[] daysTimes_1 = daysTimes[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + string[] daysTimes_2 = daysTimes[1].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + + if (daysTimes_1.Length == 2 && daysTimes_2.Length == 2) + { + int startWdIndex = (int)Enum.Parse(typeof(Weekdays), daysTimes_1[0]); + int endWdIndex = (int)Enum.Parse(typeof(Weekdays), daysTimes_2[0]); + + if (startWdIndex < endWdIndex) + { + _periodicsList.Add((Weekdays)startWdIndex + " " + daysTimes_1[1] + " to 23:59"); + + for (int i = startWdIndex + 1; i <= endWdIndex - 1; i++) + { + _periodicsList.Add((Weekdays)i + " 0:00 to 23:59"); + } + + _periodicsList.Add((Weekdays)endWdIndex + " 0:00 to " + daysTimes_2[1]); + } + else + { + int firstWdIndex = (int)Enum.GetValues(typeof(Weekdays)).Cast().First(); + int lastWdIndex = (int)Enum.GetValues(typeof(Weekdays)).Cast().Last(); + + _periodicsList.Add((Weekdays)startWdIndex + " " + daysTimes_1[1] + " to 23:59"); + + for (int i = startWdIndex + 1; i <= lastWdIndex; i++) + { + _periodicsList.Add((Weekdays)i + " 0:00 to 23:59"); + } + + for (int i = firstWdIndex; i <= endWdIndex - 1; i++) + { + _periodicsList.Add((Weekdays)i + " 0:00 to 23:59"); + } + + _periodicsList.Add((Weekdays)endWdIndex + " 0:00 to " + daysTimes_2[1]); + } + } + else + { + _periodicsList.Add(period); + } + } + } + } + } + + public class Cisco_Interface : CiscoCommand + { + public string InterfaceName { get; set; } + public int SecurityLevel { get; set; } + public string VLan { get; set; } + public string IpAddress { get; set; } + public string Netmask { get; set; } + public bool Shutdown { get; set; } + public bool ManagementOnly { get; set; } + public bool LeadsToInternet { get; set; } + + public class Subnet + { + public string Network { get; private set; } + public string Netmask { get; private set; } + + public Subnet(string sIp, string sMask) + { + Network = sIp; + Netmask = sMask; + } + } + + public List Topology = new List(); + + public override string Name() { return "interface"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + InterfaceName = command.GetParam(1); + SecurityLevel = 0; + VLan = ""; + IpAddress = ""; + Netmask = ""; + Shutdown = false; + ManagementOnly = false; + LeadsToInternet = false; + + if (command.Children == null) + { + return; + } + + foreach (CiscoCommand child in command.Children) + { + switch (child.Name()) + { + case "security-level": + int securityLevel; + if (int.TryParse(((Cisco_SecurityLevel)child).Value, out securityLevel)) + { + SecurityLevel = securityLevel; + } + break; + + case "nameif": + CiscoId = ((Cisco_NameIf)child).Value; + break; + + case "vlan": + VLan = ((Cisco_VLan)child).Value; + break; + + case "shutdown": + Shutdown = ((Cisco_Shutdown)child).IsShutdown; + break; + + case "management-only": + ManagementOnly = ((Cisco_ManagementOnly)child).IsManagementOnly; + break; + + case "ip address": + IpAddress = ((Cisco_IP)child).IpAddress; + Netmask = ((Cisco_IP)child).Netmask; + + if (NetworkUtils.IsValidIpv4(IpAddress) && NetworkUtils.IsValidNetmaskv4(Netmask)) + { + Topology.Add(new Subnet(NetworkUtils.GetNetwork(IpAddress, Netmask), Netmask)); + } + else + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid IP subnet (" + IpAddress + "/" + Netmask + ")."; + Console.WriteLine(ConversionIncidentMessage); + } + break; + } + } + } + + public bool HasValidIpAddress() + { + return NetworkUtils.IsValidIp(IpAddress) && NetworkUtils.IsValidNetmaskv4(Netmask); + } + } + + public class Cisco_Route : CiscoCommand + { + public string InterfaceName { get; set; } + public bool DefaultRoute { get; set; } + public string DestinationIp { get; set; } + public string DestinationNetmask { get; set; } + public string Gateway { get; set; } + + public override string Name() { return "route"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + DefaultRoute = false; + InterfaceName = command.GetParam(1); + DestinationIp = command.GetParam(2); + DestinationNetmask = command.GetParam(3); + Gateway = command.GetParam(4); + + bool destinationIpResolved = false; + + if (ciscoIds.ContainsKey(DestinationIp)) + { + var refObj = (Cisco_Object)ciscoIds[DestinationIp]; + if (refObj != null) + { + switch (refObj.ObjectType) + { + case Cisco_Object.ObjectTypes.Host: + DestinationIp = refObj.HostAddress; + destinationIpResolved = true; + break; + + case Cisco_Object.ObjectTypes.Network: + DestinationIp = refObj.Network; + destinationIpResolved = true; + break; + } + } + } + else + { + DestinationIp = aliases.ContainsKey(DestinationIp) ? aliases[DestinationIp] : DestinationIp; + destinationIpResolved = true; + } + + if (!destinationIpResolved) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Cannot resolve route destination IP address (" + command.GetParam(2) + "). Using IP 1.1.1.1."; + Console.WriteLine(ConversionIncidentMessage); + + DestinationIp = "1.1.1.1"; + DestinationNetmask = "255.255.255.255"; + } + + if (!NetworkUtils.IsValidIp(DestinationIp)) + { + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Invalid IP address (" + DestinationIp + "). Using IP 1.1.1.1."; + Console.WriteLine(ConversionIncidentMessage); + + DestinationIp = "1.1.1.1"; + DestinationNetmask = "255.255.255.255"; + } + + if (DestinationIp == "0.0.0.0" && DestinationNetmask == "0.0.0.0") + { + DefaultRoute = true; + } + } + } + + public class Cisco_AntiSpoofing : CiscoCommand + { + public string InterfaceName { get; set; } + + public override string Name() { return "ip verify reverse-path interface"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + if (command.GetParam(1) == "verify" && command.GetParam(2) == "reverse-path" && command.GetParam(3) == "interface") + { + InterfaceName = command.GetParam(4); + } + } + } + + public class Cisco_SameSecurityTraffic : CiscoCommand + { + public enum InterfaceTrafficType { NA, Inter, Intra }; + + public InterfaceTrafficType TrafficType { get; set; } + + public override string Name() { return "same-security-traffic"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + if (command.GetParam(1) == "permit") + { + switch (command.GetParam(2)) + { + case "inter-interface": + TrafficType = InterfaceTrafficType.Inter; + break; + + case "intra-interface": + TrafficType = InterfaceTrafficType.Intra; + break; + } + } + } + } + + public class Cisco_Nat : CiscoCommand + { + public bool Inactive { get; set; } + public string RealInterface { get; set; } + public string MappedInterface { get; set; } + public bool IsStatic { get; set; } + public bool IsHideBehindInterface { get; set; } + public bool IsUnidirectional { get; set; } + public bool IsAutoAfter { get; set; } + public string StaticNatIpAddressOrObjectName { get; set; } + public string DynamicNatIpAddressOrObjectName { get; set; } + public string SourceId { get; set; } + public string TranslatedSourceId { get; set; } + public string DestinationId { get; set; } + public string TranslatedDestinationId { get; set; } + public string ServiceProtocol { get; set; } + public string ServiceId { get; set; } + public string TranslatedServiceId { get; set; } + + public override string Name() { return "nat"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + /************************************************************************************** + * There are two types of NAT: + * 1. Object NAT - child object of a Network Object - this is the commonly used NAT + * 2. Regular NAT - twice or manual NAT rule - more scalable, enables extra features over Object NAT + * + * Each of these two types may be Static or Dynamic. + * Static NAT allows bidirectional traffic (mirrored rules). + * + * Each NAT command is started as follows: + * --------------------------------------- + * nat [(real_interface, mapped_interface)] ... + * + **************************************************************************************/ + + base.Parse(command, prevCommand, ciscoIds, aliases); + + string param = command.GetParam(1).Trim(new char[] { '(', ')' }); + string[] interfaces = param.Split(','); + + if (interfaces.Length > 0) + { + RealInterface = interfaces[0]; + MappedInterface = (interfaces.Length > 1) ? interfaces[1] : ""; + } + else + { + RealInterface = ""; + MappedInterface = ""; + } + + Inactive = false; + IsStatic = false; + IsHideBehindInterface = false; + IsUnidirectional = false; + StaticNatIpAddressOrObjectName = ""; + DynamicNatIpAddressOrObjectName = ""; + SourceId = ""; + TranslatedSourceId = ""; + DestinationId = ""; + TranslatedDestinationId = ""; + ServiceProtocol = ""; + ServiceId = ""; + TranslatedServiceId = ""; + + if (command.IndentationLevel > 0) + { + ParseObjectNatCommand(command, prevCommand, ciscoIds); + } + else + { + ParseRegularNatCommand(command, prevCommand, ciscoIds); + } + + if (command.GetParamPosition("unidirectional") > 0/* || command.GetParamPosition("no-proxy-arp") > 0*/) // commented due to A.R. suggestion... + { + IsUnidirectional = true; + } + + if (command.GetParamPosition("inactive") > 0) + { + Inactive = true; + } + } + + private void ParseObjectNatCommand(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds) + { + /******************************************************** + * Parsing options for Object NAT: + * ------------------------------- + * ... static {mapped_host_ip_address | mapped_object_name | interface} [service {tcp | udp} real_port mapped_port] + * + * ... dynamic {mapped_host_ip_address | mapped_object_name | interface} + * + * + mapped_object may be a host or network or range + */ + + switch (command.GetParam(2)) + { + case "static": + IsStatic = true; + + if (command.GetParam(3) == "interface") + { + IsHideBehindInterface = true; // Static NAT with port-translation + } + else + { + // static hide behind an arbitrary ip/network + StaticNatIpAddressOrObjectName = command.GetParam(3); + } + + int servicePos = command.GetParamPosition("service"); + if (servicePos > 0) + { + ServiceProtocol = command.GetParam(servicePos + 1); + if (ServiceProtocol == "tcp" || ServiceProtocol == "udp") + { + ServiceId = CiscoKnownServices.ConvertServiceToPort(command.GetParam(servicePos + 2)); + TranslatedServiceId = CiscoKnownServices.ConvertServiceToPort(command.GetParam(servicePos + 3)); + } + else + { + ServiceProtocol = ""; + + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Unrecognized service protocol (" + ServiceProtocol + ")"; + Console.WriteLine(ConversionIncidentMessage); + } + } + break; + + case "dynamic": + if (command.GetParam(3) == "interface") + { + IsHideBehindInterface = true; + } + else + { + // dynamic hide behind an arbitrary ip/network + DynamicNatIpAddressOrObjectName = command.GetParam(3); + } + + // Check for interface fall-back configuration + if (command.GetParam(4) == "interface") + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Interface fall-back for dynamic object NAT is not supported"; + Console.WriteLine(ConversionIncidentMessage); + } + break; + } + } + + private void ParseRegularNatCommand(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds) + { + /******************************************************** + * Parsing options for regular (manual or twice) NAT: + * -------------------------------------------------- + * ... [after-object] source static real_object_name [mapped_object_name | interface] [destination static mapped_object_name real_object_name] [service real_service_name mapped_service_name] + * + * ... [after-auto] source dynamic {real_object_name | any} {mapped_object_name | interface} [destination static mapped_object_name real_object_name] [service mapped_service_name real_service_name] + * + * + real_object/mapped_object may be a host or network + */ + + int sourcePos = 2; + + if (command.GetParam(2) == "after-auto" || command.GetParam(2) == "after-object") + { + IsAutoAfter = true; + sourcePos = 3; + } + + if (command.GetParam(sourcePos) == "source") + { + if (command.GetParam(sourcePos + 1) == "static") + { + IsStatic = true; + } + + SourceId = command.GetParam(sourcePos + 2); + TranslatedSourceId = command.GetParam(sourcePos + 3); + if (TranslatedSourceId == "interface") + { + IsHideBehindInterface = true; + } + + int destPos = command.GetParamPosition("destination"); + if (destPos > 0) // twice-NAT + { + // check sanity + if (command.GetParam(destPos + 1) != "static") + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Not handling NAT with dynamic destination"; + Console.WriteLine(ConversionIncidentMessage); + return; + } + + DestinationId = command.GetParam(destPos + 2); + TranslatedDestinationId = command.GetParam(destPos + 3); + } + + int servicePos = command.GetParamPosition("service"); + if (servicePos > 0) + { + ServiceId = command.GetParam(servicePos + 1); + TranslatedServiceId = command.GetParam(servicePos + 2); + } + } + else + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Not handling NAT with dynamic source"; + Console.WriteLine(ConversionIncidentMessage); + } + } + } + + public class Cisco_AccessGroup : CiscoCommand + { + public enum DirectionType { Inbound, Outbound, Global }; + + public DirectionType Direction { get; set; } + public string AccessListName { get; set; } + public string InterfaceName { get; set; } + + public override string Name() { return "access-group"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + // Parsing Options: + //----------------- + // access-group access_list_name {{in | out} interface interface_name | global} + //----------------- + + base.Parse(command, prevCommand, ciscoIds, aliases); + + AccessListName = command.GetParam(1); + InterfaceName = (command.GetParam(3) == "interface") ? command.GetParam(4) : ""; + + switch (command.GetParam(2)) + { + case "in": + Direction = DirectionType.Inbound; + break; + + case "out": + Direction = DirectionType.Outbound; + break; + + case "global": + Direction = DirectionType.Global; + break; + + default: + Console.WriteLine("Error: unknown access-group traffic direction (" + command.GetParam(2) + ")."); + break; + } + + if (Direction != DirectionType.Inbound && Direction != DirectionType.Global) + { + ConversionIncidentType = ConversionIncidentType.Informative; + ConversionIncidentMessage = "Outbound ACLs will not be converted"; + Console.WriteLine(ConversionIncidentMessage); + } + } + } + + public class Cisco_AccessList : CiscoCommand + { + public enum ActionType { NA, Deny, Permit }; + + public class SourceDest + { + public enum SourceDestType { NA, Any, Any6, ReferenceObject, Host, SubnetAndMask }; + + public SourceDestType Type { get; set; } + public string HostIp { get; set; } + public string Subnet { get; set; } + public string Netmask { get; set; } + public string RefObjectName { get; set; } + public int WordsCount { get; set; } + + public SourceDest() + { + Type = SourceDestType.NA; + HostIp = ""; + Subnet = ""; + Netmask = ""; + RefObjectName = ""; + WordsCount = -1; + } + + public SourceDest(List words) : this() + { + if (!words.Any()) + { + WordsCount = 0; + return; + } + + switch (words[0]) + { + case "any": + case "any4": + Type = SourceDestType.Any; + WordsCount = 1; + break; + + case "any6": + Type = SourceDestType.Any6; + WordsCount = 1; + break; + + case "host": + Type = SourceDestType.Host; + if (words.Count > 1) + { + HostIp = words[1]; + WordsCount = 2; + } + break; + + case "object-group": + case "object": + Type = SourceDestType.ReferenceObject; + if (words.Count > 1) + { + RefObjectName = words[1]; + WordsCount = 2; + } + break; + + case "interface": + Type = SourceDestType.ReferenceObject; + if (words.Count > 1) + { + RefObjectName = InterfacePrefix + words[1]; + WordsCount = 2; + } + break; + + default: + // both the ip_address and ip_mask are specified + Type = SourceDestType.SubnetAndMask; + if (words.Count > 1) + { + Subnet = words[0]; + Netmask = words[1]; + WordsCount = 2; + } + break; + } + } + } + + public class ProtocolProperties + { + private Dictionary _ciscoIds; + + public ProtocolType Protocol { get; set; } + public TcpUdpPortOperatorType TcpUdpPortOperator { get; set; } + public ServiceDirection Where { get; set; } + public string TcpUdpPortValue { get; set; } + public int WordsCount { get; set; } + + public ProtocolProperties() + { + Protocol = ProtocolType.NA; + TcpUdpPortOperator = TcpUdpPortOperatorType.NA; + Where = ServiceDirection.Destination; + TcpUdpPortValue = ""; + WordsCount = -1; + } + + public ProtocolProperties(ProtocolType protocol, List words, Dictionary ciscoIds, ServiceDirection where) : this() + { + _ciscoIds = ciscoIds; + Protocol = protocol; + Where = where; + WordsCount = 0; + + if (protocol == ProtocolType.Ip || + protocol == ProtocolType.Tcp || + protocol == ProtocolType.Udp || + protocol == ProtocolType.ReferenceObject) + { + TcpUdpPortOperator = TcpUdpPortOperatorType.All; + + if (words.Count > 0) + { + switch (words[0]) + { + case "range": + TcpUdpPortOperator = TcpUdpPortOperatorType.Range; + if (words.Count > 2) + { + TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]) + "-" + + CiscoKnownServices.ConvertServiceToPort(words[2]); + WordsCount = 3; + } + break; + + case "lt": + TcpUdpPortOperator = TcpUdpPortOperatorType.Lt; + if (words.Count > 1) + { + TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); + WordsCount = 2; + } + break; + + case "gt": + TcpUdpPortOperator = TcpUdpPortOperatorType.Gt; + if (words.Count > 1) + { + TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); + WordsCount = 2; + } + break; + + case "eq": + TcpUdpPortOperator = TcpUdpPortOperatorType.Eq; + if (words.Count > 1) + { + TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); + WordsCount = 2; + } + break; + + case "neq": + TcpUdpPortOperator = TcpUdpPortOperatorType.Neq; + if (words.Count > 1) + { + TcpUdpPortValue = CiscoKnownServices.ConvertServiceToPort(words[1]); + WordsCount = 2; + } + break; + + + case "object": + if (words.Count > 1 && IsServiceObject(words[1])) + { + TcpUdpPortOperator = TcpUdpPortOperatorType.ReferenceObject; + TcpUdpPortValue = words[1]; + WordsCount = 2; + } + break; + + case "object-group": + if (words.Count > 1 && IsServiceGroup(words[1])) + { + TcpUdpPortOperator = TcpUdpPortOperatorType.ReferenceObject; + TcpUdpPortValue = words[1]; + WordsCount = 2; + } + break; + } + } + } + else if (protocol == ProtocolType.Icmp || protocol == ProtocolType.Icmp6) + { + if (words.Count > 0) + { + switch (words[0]) + { + case "object-group": + if (words.Count > 1 && IsServiceGroup(words[1])) + { + TcpUdpPortOperator = TcpUdpPortOperatorType.ReferenceObject; + TcpUdpPortValue = words[1]; + WordsCount = 2; + } + break; + + default: + if (CiscoKnownServices.IsKnownIcmpService(words[0])) + { + TcpUdpPortOperator = TcpUdpPortOperatorType.Eq; + TcpUdpPortValue = CiscoKnownServices.ConvertIcmpServiceToType(words[0]); + WordsCount = 1; + } + break; + } + } + } + else if (protocol == ProtocolType.KnownOtherIpProtocol) + { + } + } + + private bool IsServiceGroup(string name) + { + if (_ciscoIds.ContainsKey(name) && _ciscoIds[name].Name() == "object-group") + { + var group = (Cisco_GroupObject)_ciscoIds[name]; + if (group.GroupType == Cisco_GroupObject.Group_Type.Service || group.GroupType == Cisco_GroupObject.Group_Type.Icmp) + { + return true; + } + } + + return false; + } + + private bool IsServiceObject(string name) + { + if (_ciscoIds.ContainsKey(name) && _ciscoIds[name].Name() == "object") + { + var obj = (Cisco_Object)_ciscoIds[name]; + if (obj.ObjectType == Cisco_Object.ObjectTypes.TcpService || + obj.ObjectType == Cisco_Object.ObjectTypes.UdpService || + obj.ObjectType == Cisco_Object.ObjectTypes.IcmpService) + { + return true; + } + } + + return false; + } + } + + public string ACLName { get; set; } + public bool Inactive { get; set; } + public ActionType Action { get; set; } + public ProtocolType Protocol { get; set; } + public string ProtocolReference { get; set; } + public string Remark { get; set; } + public bool IsRemark { get; set; } + public bool IsTimeRangeSpecified { get; set; } + public string TimeRangeName { get; set; } + public SourceDest Source { get; set; } + public SourceDest Destination { get; set; } + public ProtocolProperties SourceProperties { get; set; } + public ProtocolProperties DestinationProperties { get; set; } + + public override string Name() { return "access-list"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + /* + * OPTION I - REMARK format - the easiest option: + * + access-list access_list_name remark text + Example: + hostname(config)# access-list ACL_OUT remark - this is the inside admin address + * + * OPTION II - STANDARD format - used for a limited number of features, such as route maps or VPN filters. + * uses IPv4 addresses only, and defines destination addresses only. + * + access-list access_list_name standard {deny | permit} {any/any4 | host ip_address | ip_address ip_mask} + Example: + hostname(config)# access-list OSPF standard permit 192.168.1.0 255.255.255.0 + * + * OPTION III.I - EXTENDED format - for ICMP based traffic matching + * + access-list access_list_name extended {deny | permit} icmp source_address_argument dest_address_argument [icmp_argument] [time-range time_range_name] [inactive] + Example: + hostname(config)# access-list ACL_IN extended permit icmp any any echo + * + * OPTION III.II - EXTENDED format - for TCP and UDP based traffic matching, with ports + * + access-list access_list_name extended {deny | permit} {tcp | udp} source_address_argument [port_argument] dest_address_argument [port_argument] [time-range time_range_name] [inactive] + Example: + hostname(config)# access-list ACL_IN extended deny tcp any host 209.165.201.29 eq www + hostname(config)# access-list ACL_IN extended deny tcp 192.168.1.0 255.255.255.0 209.165.201.0 255.255.255.224 + * + * OPTION III.III - EXTENDED format - for general IP address and FQDN based matching + * + access-list access_list_name extended {deny | permit} protocol_argument source_address_argument dest_address_argument [time-range time_range_name] [inactive] + Example: + hostname(config)# access-list ACL_IN extended permit ip any any + * + * ********************** + * ACL COMMAND ARGUMENTS: + * + * protocol_argument specification: one of the following options: + * -------------------------------------------------------------- + * protocol_name/protocol_number + * object service_object_id --> may be also a icmp service object + * object-group service_group_id + * object-group protocol_group_id + * + * source_address_argument/dest_address_argument specification: one of the following options: + * ------------------------------------------------------------------------------------------ + * any/any4/any6 + * host ip_address + * interface interface_name + * object network_object_id + * object-group network_group_id + * ip_address ip_mask + * + * icmp_argument specification: one of the following options: + * ---------------------------------------------------------- + * icmp_type + * object-group icmp_group_id --> object-group icmp-type command + * + * port_argument specification: one of the following options: + * ---------------------------------------------------------- + * operator port --> where operator can be one of: lt, gt, eq, neq, range; port can be number or name of a TCP or UDP port + * object-group service_group_id + * + */ + + base.Parse(command, prevCommand, ciscoIds, aliases); + + ACLName = command.GetParam(1); + Inactive = false; + Action = ActionType.NA; + Protocol = ProtocolType.NA; + ProtocolReference = ""; + Remark = ""; + IsRemark = false; + IsTimeRangeSpecified = false; + + var prevAclCommand = prevCommand as Cisco_AccessList; + + if (command.GetParam(2) == "remark") + { + IsRemark = true; + + // Note that there may be several consecutive remark lines, so we need to aggregate to a single remark + string dataForNextElement = ""; + if (prevAclCommand != null && prevAclCommand.IsRemark && !string.IsNullOrEmpty(prevAclCommand.DataForNextElement)) + { + dataForNextElement = prevAclCommand.DataForNextElement; + } + + string text = command.Text.Trim(); + int offset = text.IndexOf("remark") + 7; + + if (!string.IsNullOrEmpty(dataForNextElement)) + { + dataForNextElement += ", "; + } + + dataForNextElement += text.Substring(offset).Trim(); + DataForNextElement = dataForNextElement; + + return; + } + + if (prevAclCommand != null && ACLName.Equals(prevAclCommand.ACLName) && !string.IsNullOrEmpty(prevAclCommand.DataForNextElement)) + { + Remark = prevAclCommand.DataForNextElement; + + if (CiscoParser.SpreadAclRemarks) + { + DataForNextElement = Remark; + } + } + + int denyPosition = command.GetParamPosition("deny"); + int permitPosition = command.GetParamPosition("permit"); + int protocolPosition = Math.Max(denyPosition, permitPosition) + 1; // protocol field should follow the action field (either deny or permit) + int sourcePosition = protocolPosition + 1; + + if (denyPosition > 0) + { + Action = ActionType.Deny; + } + + if (permitPosition > 0) + { + Action = ActionType.Permit; + } + + if (command.GetParam(2) == "standard") + { + Protocol = ProtocolType.Ip; + + Source = new SourceDest + { + Type = SourceDest.SourceDestType.Any + }; + + SourceProperties = new ProtocolProperties + { + Protocol = Protocol, + TcpUdpPortOperator = TcpUdpPortOperatorType.All + }; + + Destination = new SourceDest(command.GetParams(4)); + + DestinationProperties = new ProtocolProperties + { + Protocol = Protocol, + TcpUdpPortOperator = TcpUdpPortOperatorType.All + }; + + return; + } + + if (command.GetParamPosition("time-range") > 0) + { + IsTimeRangeSpecified = true; + int indexTimeRange = command.GetParamPosition("time-range"); + TimeRangeName = command.GetParam(indexTimeRange + 1); + } + + if (command.GetParamPosition("inactive") > 0) + { + Inactive = true; + } + + string strProtocol = command.GetParam(protocolPosition); + switch (strProtocol) + { + case "ip": + Protocol = ProtocolType.Ip; + break; + + case "icmp": + Protocol = ProtocolType.Icmp; + break; + + case "icmp6": + Protocol = ProtocolType.Icmp6; + break; + + case "udp": + Protocol = ProtocolType.Udp; + break; + + case "tcp": + Protocol = ProtocolType.Tcp; + break; + + case "object-group": + case "object": + Protocol = ProtocolType.ReferenceObject; + ProtocolReference = command.GetParam(protocolPosition + 1); + sourcePosition++; + break; + + default: + string serviceName; + if (CiscoKnownServices.IsKnownService(strProtocol)) + { + Protocol = ProtocolType.KnownOtherIpProtocol; + } + else if (CiscoKnownServices.IsKnownServiceNumber(strProtocol, out serviceName)) // protocol number is used!!! + { + Protocol = ProtocolType.KnownOtherIpProtocol; + strProtocol = serviceName; + } + else + { + ProtocolReference = strProtocol; + ConversionIncidentType = ConversionIncidentType.ManualActionRequired; + ConversionIncidentMessage = "Unrecognized service protocol (" + strProtocol + ")"; + Console.WriteLine(ConversionIncidentMessage); + } + break; + } + + Source = new SourceDest(command.GetParams(sourcePosition)); + SourceProperties = new ProtocolProperties(Protocol, command.GetParams(sourcePosition + Source.WordsCount), ciscoIds, ServiceDirection.Source); + Destination = new SourceDest(command.GetParams(sourcePosition + Source.WordsCount + SourceProperties.WordsCount)); + DestinationProperties = new ProtocolProperties(Protocol, command.GetParams(sourcePosition + Source.WordsCount + SourceProperties.WordsCount + Destination.WordsCount), ciscoIds, ServiceDirection.Destination); + + if (Protocol == ProtocolType.KnownOtherIpProtocol) + { + // This information is needed in order to create/query appropriate service objects + DestinationProperties.TcpUdpPortValue = strProtocol; + DestinationProperties.WordsCount = 1; + } + } + } + + public class Cisco_ClassMap : CiscoCommand + { + public string ClassMapName; + public List MatchedAclNames = new List(); + + public override string Name() { return "class-map"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + base.Parse(command, prevCommand, ciscoIds, aliases); + + ClassMapName = command.GetParam(1); + + if (command.Children == null) + { + return; + } + + foreach (CiscoCommand child in command.Children) + { + if (child.Name() == "match" && !string.IsNullOrEmpty(((Cisco_Match_AccessList)child).AccessListName)) + { + MatchedAclNames.Add(((Cisco_Match_AccessList)child).AccessListName); + } + } + } + } + + public class Cisco_Match_AccessList : CiscoCommand + { + public string AccessListName { get; set; } + + public override string Name() { return "match"; } + + public override void Parse(CiscoCommand command, CiscoCommand prevCommand, Dictionary ciscoIds, Dictionary aliases) + { + // Parsing Options: + //----------------- + // match access-list access_list_name + //----------------- + + base.Parse(command, prevCommand, ciscoIds, aliases); + + AccessListName = (command.GetParam(1) == "access-list") ? command.GetParam(2) : ""; + } + } +} diff --git a/CiscoMigration/CiscoConverter.cs b/CiscoMigration/CiscoConverter.cs index f7cb4deb..00b23789 100644 --- a/CiscoMigration/CiscoConverter.cs +++ b/CiscoMigration/CiscoConverter.cs @@ -54,29 +54,27 @@ private class CiscoNetwork public int CiscoCommandId { get; private set; } public string IpAddress { get; private set; } public string NetMask { get; private set; } + public string MaskPrefix { get; set; } - public CiscoNetwork(int ciscoCommandId, string sIp) + public CiscoNetwork(int ciscoCommandId, string sIp) : this(ciscoCommandId, sIp, "") { } + public CiscoNetwork(int ciscoCommandId, string sIp, string sMask) : this(ciscoCommandId, sIp, sMask, "") { } + public CiscoNetwork(int ciscoCommandId, string sIp, string sMask, string sMaskPrefix) { CiscoCommandId = ciscoCommandId; IpAddress = sIp; - NetMask = "255.255.255.255"; - } - - public CiscoNetwork(int ciscoCommandId, string sIp, string sMask) - { - CiscoCommandId = ciscoCommandId; - IpAddress = sIp; - NetMask = string.IsNullOrEmpty(sMask) ? "255.255.255.255" : sMask; + NetMask = string.IsNullOrEmpty(sMask) && string.IsNullOrEmpty(sMaskPrefix) ? "255.255.255.255" : sMask; + MaskPrefix = sMaskPrefix; } public bool IsHost() { - return NetworkUtils.IsValidIp(IpAddress) && (NetworkUtils.GetMaskLength(NetMask) == 32); + return NetworkUtils.IsValidIpv4(IpAddress) && (NetworkUtils.GetMaskLength(NetMask) == 32) || NetworkUtils.IsValidIpv6(IpAddress) && string.IsNullOrEmpty(MaskPrefix); } public bool IsNetwork() { - return NetworkUtils.IsValidIp(IpAddress) && NetworkUtils.IsValidNetmask(NetMask) && (NetworkUtils.GetMaskLength(NetMask) < 32); + return NetworkUtils.IsValidIpv4(IpAddress) && NetworkUtils.IsValidNetmaskv4(NetMask) && (NetworkUtils.GetMaskLength(NetMask) < 32) || + NetworkUtils.IsValidIpv6(IpAddress) && !string.IsNullOrEmpty(MaskPrefix); } public string AutoGeneratedName() @@ -88,7 +86,10 @@ public string AutoGeneratedName() if (IsNetwork()) { - return "network_" + IpAddress + "_" + NetworkUtils.GetMaskLength(NetMask); + if (!string.IsNullOrEmpty(NetMask)) + return "network_" + IpAddress + "_" + NetworkUtils.GetMaskLength(NetMask); + else + return "network_" + IpAddress + "_" + MaskPrefix; } Console.WriteLine("Error: unrecognized network object - Ip={0}, Mask={1}", IpAddress, NetMask); @@ -97,12 +98,15 @@ public string AutoGeneratedName() public string AutoGeneratedNetworkName() { - if (NetworkUtils.IsValidIp(IpAddress) && NetworkUtils.IsValidNetmask(NetMask)) + if (IsNetwork()) { - return "network_" + IpAddress + "_" + NetworkUtils.GetMaskLength(NetMask); + if (!string.IsNullOrEmpty(NetMask)) + return "network_" + IpAddress + "_" + NetworkUtils.GetMaskLength(NetMask); + else + return "network_" + IpAddress + "_" + MaskPrefix; } - Console.WriteLine("Error: unrecognized network object - Ip={0}, Mask={1}", IpAddress, NetMask); + Console.WriteLine("Error: unrecognized network object - Ip={0}, Mask={1}, Prefix={2}", IpAddress, NetMask, MaskPrefix); return "_Err_in_network-line_" + CiscoCommandId; } @@ -119,12 +123,12 @@ public override bool Equals(object obj) return false; } - return (other.IpAddress == IpAddress && other.NetMask == NetMask); + return (other.IpAddress == IpAddress && other.NetMask == NetMask && other.MaskPrefix == MaskPrefix); } public override int GetHashCode() { - string hash = IpAddress + "," + NetMask; + string hash = IpAddress + "," + NetMask + "," + MaskPrefix; return hash.GetHashCode(); } } @@ -160,6 +164,10 @@ public static ProtocolType ProtocolStringToProtocolType(ref string sProtocol) protocol = ProtocolType.Icmp; break; + case "icmp6": + protocol = ProtocolType.Icmp6; + break; + case "ip": protocol = ProtocolType.Ip; break; @@ -287,6 +295,11 @@ public static string AutoGeneratedName(CheckPointObjectsRepository cpObjects, Pr name = cpObjects.GetKnownServiceName(name, out serviceFound); return serviceFound ? name : "icmp-proto"; + case ProtocolType.Icmp6: + name = "ICMP_" + CiscoKnownServices.ConvertIcmpServiceToType(sPort); + name = cpObjects.GetKnownServiceName(name, out serviceFound); + return serviceFound ? name : "IPv6-ICMP"; + case ProtocolType.Ip: if (portOperator == TcpUdpPortOperatorType.All) { @@ -447,7 +460,7 @@ public static bool CheckServicesPortRangesOverlapping(CheckPointObject subsetSer int subsetTcpPortFrom, subsetTcpPortTo; int supersetTcpPortFrom, supersetTcpPortTo; - if (subsetService.GetType() == typeof (CheckPoint_TcpService) && supersetService.GetType() == typeof (CheckPoint_TcpService)) + if (subsetService.GetType() == typeof(CheckPoint_TcpService) && supersetService.GetType() == typeof(CheckPoint_TcpService)) { var subsetTcp = (CheckPoint_TcpService)subsetService; var supersetTcp = (CheckPoint_TcpService)supersetService; @@ -455,7 +468,7 @@ public static bool CheckServicesPortRangesOverlapping(CheckPointObject subsetSer GetServicePortRanges(subsetTcp.Port, out subsetTcpPortFrom, out subsetTcpPortTo); GetServicePortRanges(supersetTcp.Port, out supersetTcpPortFrom, out supersetTcpPortTo); } - else if (subsetService.GetType() == typeof (CheckPoint_UdpService) && supersetService.GetType() == typeof (CheckPoint_UdpService)) + else if (subsetService.GetType() == typeof(CheckPoint_UdpService) && supersetService.GetType() == typeof(CheckPoint_UdpService)) { var subsetUdp = (CheckPoint_UdpService)subsetService; var supersetUdp = (CheckPoint_UdpService)supersetService; @@ -975,7 +988,7 @@ private void PopulateCiscoNetworkObjects() // The referenced object will be created on its own!!! if (string.IsNullOrEmpty(ciscoNetwork.ReferencedObject)) { - var network = new CiscoNetwork(command.Id, ciscoNetwork.IpAddress, ciscoNetwork.Netmask); + var network = new CiscoNetwork(command.Id, ciscoNetwork.IpAddress, ciscoNetwork.Netmask, ciscoNetwork.MaskPrefix); _ciscoNetworkObjects.Add(network); } } @@ -989,6 +1002,9 @@ private void PopulateCiscoNetworkObjects() continue; } + //if there is icmp6 service we need to create an 'other service' with name IPv6-ICMP. At this place checks if we have requirements for this service and create his if yes + CheckIcmp6Service(ciscoAcl); + CiscoNetwork source; CiscoNetwork dest; @@ -1018,6 +1034,28 @@ private void PopulateCiscoNetworkObjects() } } + private void CheckIcmp6Service(Cisco_AccessList accesslist) + { + if (accesslist.Protocol == ProtocolType.Icmp6) + { + CheckPoint_OtherService icmp6 = new CheckPoint_OtherService("IPv6-ICMP", "58", "", new List()); + if (_cpOtherServices.Count > 0) + { + foreach (CheckPoint_OtherService service in _cpOtherServices) + { + if (service.Name.Equals(icmp6.Name)) + return; + } + _cpOtherServices.Add(icmp6); + } + else + { + _cpOtherServices.Add(icmp6); + } + return; + } + } + private void CheckCiscoInterfacesTraffic() { var ciscoInterfacesTraffic = _ciscoParser.Filter("same-security-traffic"); @@ -1076,6 +1114,7 @@ private void Add_Networks() cpNetwork.Name = network.AutoGeneratedName(); cpNetwork.Subnet = network.IpAddress; cpNetwork.Netmask = network.NetMask; + cpNetwork.MaskLength = network.MaskPrefix != null ? network.MaskPrefix : ""; cpNetwork.ConvertedCommandId = network.CiscoCommandId; AddCheckPointObject(cpNetwork); } @@ -1116,6 +1155,7 @@ private void Add_Objects() cpNetwork.Comments = ciscoObject.Description; cpNetwork.Subnet = ciscoObject.Network; cpNetwork.Netmask = ciscoObject.Netmask; + cpNetwork.MaskLength = ciscoObject.MaskPrefix != null ? ciscoObject.MaskPrefix : ""; ApplyConversionIncidentOnCheckPointObject(cpNetwork, ciscoObject); CheckObjectNameValidity(cpNetwork, ciscoObject); AddCheckPointObject(cpNetwork); @@ -1168,6 +1208,7 @@ private void Add_Objects() break; case Cisco_Object.ObjectTypes.IcmpService: + case Cisco_Object.ObjectTypes.Icmp6Service: // Predefined "icmp" object. No special handling... break; } @@ -1201,7 +1242,7 @@ private void Add_NetworkGroups() } else { - string memberName = (new CiscoNetwork(ciscoMember.Id, ciscoMember.IpAddress, ciscoMember.Netmask)).AutoGeneratedName(); + string memberName = (new CiscoNetwork(ciscoMember.Id, ciscoMember.IpAddress, ciscoMember.Netmask, ciscoMember.MaskPrefix)).AutoGeneratedName(); if (memberName.Contains(AutoGeneratedNameWithError)) { ciscoMember.ConversionIncidentType = ConversionIncidentType.ManualActionRequired; @@ -1496,6 +1537,23 @@ private void Add_ServicesAndServiceGroups() } break; + case "icmp6": + cpName = CheckPointServiceObjectsFactory.AutoGeneratedName(_cpObjects, + ProtocolType.Icmp6, + TcpUdpPortOperatorType.Eq, + ciscoService.Port, + ServiceDirection.Destination, + ciscoService.Id); + cpServiceGroup.Members.Add(cpName); + + if (cpName == "IPv6-ICMP" && !string.IsNullOrEmpty(ciscoService.Port)) + { + ciscoService.ConversionIncidentType = ConversionIncidentType.Informative; + ciscoGroup.ConversionIncidentType = ConversionIncidentType.Informative; + ciscoGroup.ConversionIncidentMessage = "Unrecognized ICMP6 service type: " + ciscoService.Port + ". Using generic IPv6-ICMP service"; + } + break; + case "ip": if (ciscoGroup.MemberObjects.Count > 1) { @@ -1692,7 +1750,7 @@ private void Add_TimeRanges() List cpTimeRangesNamesUniq = new List(); int cpTimeNamePostfixInt = 1; - foreach(CiscoCommand command in caTimesList) + foreach (CiscoCommand command in caTimesList) { if (command.GetType() == typeof(Cisco_TimeRange)) { @@ -1721,7 +1779,7 @@ private void Add_TimeRanges() cpTimeRangesNamesUniq.Add(cpTimeRangeName); } - if(isRenamed) + if (isRenamed) cpTimeNamePostfixInt += 1; } else @@ -1754,7 +1812,7 @@ private void Add_TimeRange(int caTimeId, string caTimeRangeName, string cpTimeRa new ConversionIncident( caTimeId, "TITLE: object is renamed", - "DESCRIPTION: object renamed from " + caTimeRangeName + " to " + cpTimeRangeName, + "DESCRIPTION: object renamed from " + caTimeRangeName + " to " + cpTimeRangeName, ConversionIncidentType.Informative)); } @@ -2269,14 +2327,15 @@ private void Add_Layers_And_Rules(CheckPoint_Package package) } package.SubPolicies.Add(cpLayer); + validatePackage(package); } } } private void Add_Global_Rules(CheckPoint_Package package) - { + { if (_ciscoGlobalAclCommands.Count > 0) - { + { // remove clenup rule of each sublayer if global rules exist because cleanup rule should be added after global-rules foreach (var subpolicy in package.SubPolicies) { @@ -2284,7 +2343,7 @@ private void Add_Global_Rules(CheckPoint_Package package) { var lastRule = subpolicy.Rules[subpolicy.Rules.Count - 1]; if (lastRule.IsCleanupRule()) - subpolicy.Rules.Remove(lastRule); + subpolicy.Rules.Remove(lastRule); } } @@ -2292,13 +2351,13 @@ private void Add_Global_Rules(CheckPoint_Package package) if (package.ParentLayer.Rules.Count > 0) { var lastRule = package.ParentLayer.Rules[package.ParentLayer.Rules.Count - 1]; - if (lastRule.IsCleanupRule()) - package.ParentLayer.Rules.Remove(lastRule); + if (lastRule.IsCleanupRule()) + package.ParentLayer.Rules.Remove(lastRule); } CheckPoint_Rule cpRule4GlobalLayer = new CheckPoint_Rule(); cpRule4GlobalLayer.Name = ""; - cpRule4GlobalLayer.Layer = package.NameOfAccessLayer; + cpRule4GlobalLayer.Layer = package.NameOfAccessLayer; cpRule4GlobalLayer.Source.Add(_cpObjects.GetObject(CheckPointObject.Any)); cpRule4GlobalLayer.Destination.Add(_cpObjects.GetObject(CheckPointObject.Any)); cpRule4GlobalLayer.Action = CheckPoint_Rule.ActionType.SubPolicy; @@ -2313,13 +2372,13 @@ private void Add_Global_Rules(CheckPoint_Package package) cpSubLayer4GlobalRules.ApplicationsAndUrlFiltering = true; cpSubLayer4GlobalRules.Shared = true; cpSubLayer4GlobalRules.Name = cpRule4GlobalLayer.SubPolicyName; - + package.SubPolicies.Insert(0, cpSubLayer4GlobalRules); // insert at the begging becuase Global Rules should be created before all policy foreach (var globalPolicyRule in _ciscoGlobalAclCommands) { // Append the global policy rules BELOW the existing sub-policies. - CheckPoint_Rule cpRule = Acl_To_CPRule(globalPolicyRule, cpSubLayer4GlobalRules.Name); + CheckPoint_Rule cpRule = Acl_To_CPRule(globalPolicyRule, cpSubLayer4GlobalRules.Name); cpSubLayer4GlobalRules.Rules.Add(cpRule); } @@ -2341,10 +2400,10 @@ private void Add_Global_Rules(CheckPoint_Package package) cpCleanupRule.Layer = cpSubLayer4GlobalRules.Name; cpSubLayer4GlobalRules.Rules.Add(cpCleanupRule); } - + // Fill in the shared layer with global policy rules INSIDE the existing sub-policies. foreach (CheckPoint_Layer subPolicy in package.SubPolicies) - { + { if (subPolicy.Name.Equals(cpSubLayer4GlobalRules.Name)) { continue; @@ -2353,7 +2412,7 @@ private void Add_Global_Rules(CheckPoint_Package package) CheckPoint_Rule cpSubRule4GlobalLayer = cpRule4GlobalLayer.Clone(); cpSubRule4GlobalLayer.Name = "Global Layer"; cpSubRule4GlobalLayer.Layer = subPolicy.Name; - subPolicy.Rules.Add(cpSubRule4GlobalLayer); + subPolicy.Rules.Add(cpSubRule4GlobalLayer); } @@ -2378,11 +2437,11 @@ private void Add_Global_Rules(CheckPoint_Package package) { // This is done to avoid duplication of incident reporting over all matched sub-policy rules. ConversionIncidentType aclConversionIncident = ciscoAcl.ConversionIncidentType; - ciscoAcl.ConversionIncidentType = ConversionIncidentType.None; + ciscoAcl.ConversionIncidentType = ConversionIncidentType.None; var cpRule = Acl_To_CPRule(ciscoAcl, subPolicy.Name); - - cpRule.Layer = subPolicy.Name; + + cpRule.Layer = subPolicy.Name; if (!string.IsNullOrEmpty(subPolicy.Tag) && subPolicy.Tag == "InterfaceDisabled") { @@ -2407,21 +2466,21 @@ private void Add_Global_Rules(CheckPoint_Package package) } } } - } - } - } + } + } + } } private CheckPoint_Rule Acl_To_CPRule(Cisco_AccessList ciscoAcl, string layerName) { - var cpRule = new CheckPoint_Rule(); - cpRule.Name = ciscoAcl.Description; - cpRule.Enabled = !ciscoAcl.Inactive; - if (layerName != null) - cpRule.Layer = layerName; - else + var cpRule = new CheckPoint_Rule(); + cpRule.Name = ciscoAcl.Description; + cpRule.Enabled = !ciscoAcl.Inactive; + if (layerName != null) + cpRule.Layer = layerName; + else cpRule.Layer = ciscoAcl.ACLName; - + cpRule.Comments = ciscoAcl.Remark; cpRule.ConversionComments = ciscoAcl.Id + ") " + ciscoAcl.Text; @@ -2606,7 +2665,7 @@ private CheckPoint_Rule Acl_To_CPRule(Cisco_AccessList ciscoAcl, string layerNam { Add_AclPorts_To_CPRule(ciscoAcl, ciscoGroupReferenceObject.ServiceProtocol, ciscoGroupReferenceObject, cpRule); } - else if (ciscoGroupReferenceObject.GroupType == Cisco_GroupObject.Group_Type.Icmp) + else if (ciscoGroupReferenceObject.GroupType == Cisco_GroupObject.Group_Type.Icmp || ciscoGroupReferenceObject.GroupType == Cisco_GroupObject.Group_Type.Icmp6) { Add_AclIcmpTypes_To_CPRule(ciscoAcl, ciscoGroupReferenceObject, cpRule); } @@ -2692,6 +2751,21 @@ private CheckPoint_Rule Acl_To_CPRule(Cisco_AccessList ciscoAcl, string layerNam "Service details: icmp " + ciscoReferenceObject.ServicePort + "."); cpRule.Service.Add(cpObject); } + else if (ciscoReferenceObject.ObjectType == Cisco_Object.ObjectTypes.Icmp6Service) // using a predefined icmp6 object + { + string icmpName = CheckPointServiceObjectsFactory.AutoGeneratedName(_cpObjects, + ProtocolType.Icmp6, + TcpUdpPortOperatorType.Eq, + ciscoReferenceObject.ServicePort, + ServiceDirection.Destination, + ciscoAcl.Id); + cpObject = GetCheckPointObjectOrCreateDummy(icmpName, + CheckPointDummyObjectType.ServiceGroup, + ciscoAcl, + "Error creating a rule, missing information for Cisco destination service", + "Service details: icmp6 " + ciscoReferenceObject.ServicePort + "."); + cpRule.Service.Add(cpObject); + } else if (_cpObjects.HasObject(ciscoReferenceObject.CiscoId)) { if (ciscoReferenceObject.IsDestination) @@ -2747,6 +2821,11 @@ private CheckPoint_Rule Acl_To_CPRule(Cisco_AccessList ciscoAcl, string layerNam cpRule.Service.Add(_cpObjects.GetObject("icmp-proto")); } + if (ciscoAcl.Protocol == ProtocolType.Icmp6 && cpRule.Service.Count == 0) + { + cpRule.Service.Add(_cpObjects.GetObject("IPv6-ICMP")); + } + if (ciscoAcl.Protocol == ProtocolType.Tcp && cpRule.Service.Count == 0) { cpRule.Service.Add(_cpObjects.GetObject("unknown_protocol_tcp")); @@ -2865,7 +2944,7 @@ private void Add_AclServices_To_CPRule(Cisco_AccessList ciscoAcl, Cisco_GroupObj ciscoService.Port, ServiceDirection.Destination, ciscoService.Id); - if (serviceName == "icmp-proto") + if (serviceName == "icmp-proto" || serviceName == "IPv6-ICMP") { if (hasGeneralIcmpServiceMember) { @@ -3169,6 +3248,7 @@ private void Add_Layers_And_Rules_For_Other_Zones(CheckPoint_Package package) cpLayer.Rules.Add(cpCleanupRule); package.SubPolicies.Add(cpLayer); + validatePackage(package); } } } @@ -3370,7 +3450,7 @@ private void Add_object_NAT() var network = new CiscoNetwork(ciscoNat.Id, ciscoNetwork.HostAddress); var cpHostTranslated = new CheckPoint_Host(); - cpHostTranslated.Name = network.AutoGeneratedName(); + cpHostTranslated.Name = ciscoNetworkObjectName; cpHostTranslated.IpAddress = network.IpAddress; ApplyConversionIncidentOnCheckPointObject(cpHostTranslated, ciscoNat); AddCheckPointObject(cpHostTranslated); @@ -3381,10 +3461,10 @@ private void Add_object_NAT() case Cisco_Object.ObjectTypes.Network: { - var network = new CiscoNetwork(ciscoNat.Id, ciscoNetwork.Network, ciscoNetwork.Netmask); + var network = new CiscoNetwork(ciscoNat.Id, ciscoNetwork.Network, ciscoNetwork.Netmask, ciscoNetwork.MaskPrefix); var cpNetworkTranslated = new CheckPoint_Network(); - cpNetworkTranslated.Name = network.AutoGeneratedName(); + cpNetworkTranslated.Name = ciscoNetworkObjectName; cpNetworkTranslated.Subnet = network.IpAddress; cpNetworkTranslated.Netmask = network.NetMask; ApplyConversionIncidentOnCheckPointObject(cpNetworkTranslated, ciscoNat); @@ -3807,6 +3887,8 @@ private void Add_NAT_Rules() } } + PostProcessNatRule64(cpNatRule); + PostProcessNatRule46(cpNatRule); _cpPreorderedNatRules.Add(cpNatRule); bool natRuleObjectHasConversionIncident = (cpNatRule.Source != null && cpNatRule.Source.ConversionIncidentType != ConversionIncidentType.None) || @@ -3886,6 +3968,136 @@ private void Add_NAT_Rules() } } + private void PostProcessNatRule64(CheckPoint_NAT_Rule natRule) + { + var isSourceHost = false; + var isSourceNetwork = false; + var isSourceIpv6 = false; + if (natRule != null && natRule.Source != null) + { + isSourceHost = natRule.Source is CheckPoint_Host; + isSourceNetwork = natRule.Source is CheckPoint_Network; + if (isSourceHost) + { + var host = (CheckPoint_Host)natRule.Source; + isSourceIpv6 = NetworkUtils.IsValidIpv6(host.IpAddress); + } + if (isSourceNetwork) + { + var network = (CheckPoint_Network)natRule.Source; + isSourceIpv6 = NetworkUtils.IsValidIpv6(network.Subnet); + } + } + if (!isSourceIpv6) + { + // source is not Ipv6, no sense to continue + return; + } + + var isTranslatedSourceHost = false; + var isTranslatedSourceNetwork = false; + var isTranslatedSourceIpv4 = false; + if (natRule != null && natRule.TranslatedSource != null) + { + isTranslatedSourceHost = natRule.TranslatedSource is CheckPoint_Host; + isTranslatedSourceNetwork = natRule.TranslatedSource is CheckPoint_Network; + if (isTranslatedSourceHost) + { + var host = (CheckPoint_Host)natRule.TranslatedSource; + isTranslatedSourceIpv4 = NetworkUtils.IsValidIpv4(host.IpAddress); + } + if (isTranslatedSourceNetwork) + { + var network = (CheckPoint_Network)natRule.TranslatedSource; + isTranslatedSourceIpv4 = NetworkUtils.IsValidIpv4(network.Subnet); + } + } + if (!isTranslatedSourceIpv4) + { + // translated source is not Ipv4, no sense to continue + return; + } + + // change NAT rule method + natRule.Method = CheckPoint_NAT_Rule.NatMethod.Nat64; + + // a address-range should be used instead of network of host for translated source + IPRange ipRange; + if (isTranslatedSourceNetwork) + { + var network = (CheckPoint_Network)natRule.TranslatedSource; + ipRange = network.GetIPRanges().Ranges[0]; + } + else // if translated source is a host + { + var host = (CheckPoint_Host)natRule.TranslatedSource; + ipRange = host.GetIPRanges().Ranges[0]; + } + var checkpointRange = new CheckPoint_Range(); + checkpointRange.RangeFrom = NetworkUtils.Number2Ip(ipRange.Minimum); + checkpointRange.RangeTo = NetworkUtils.Number2Ip(ipRange.Maximum); + checkpointRange.Name = "r_" + checkpointRange.RangeFrom + "-" + checkpointRange.RangeTo; + if (_cpObjects.GetObject(checkpointRange.Name) == null) + { + AddCheckPointObject(checkpointRange); + } + natRule.TranslatedSource = checkpointRange; + } + + private void PostProcessNatRule46(CheckPoint_NAT_Rule natRule) + { + var isSourceHost = false; + var isSourceNetwork = false; + var isSourceIpv4 = false; + if (natRule != null && natRule.Source != null) + { + isSourceHost = natRule.Source is CheckPoint_Host; + isSourceNetwork = natRule.Source is CheckPoint_Network; + if (isSourceHost) + { + var host = (CheckPoint_Host)natRule.Source; + isSourceIpv4 = NetworkUtils.IsValidIpv4(host.IpAddress); + } + if (isSourceNetwork) + { + var network = (CheckPoint_Network)natRule.Source; + isSourceIpv4 = NetworkUtils.IsValidIpv4(network.Subnet); + } + } + if (!isSourceIpv4) + { + // source is not Ipv4, no sense to continue + return; + } + + var isTranslatedSourceHost = false; + var isTranslatedSourceNetwork = false; + var isTranslatedSourceIpv6 = false; + if (natRule != null && natRule.TranslatedSource != null) + { + isTranslatedSourceHost = natRule.TranslatedSource is CheckPoint_Host; + isTranslatedSourceNetwork = natRule.TranslatedSource is CheckPoint_Network; + if (isTranslatedSourceHost) + { + var host = (CheckPoint_Host)natRule.TranslatedSource; + isTranslatedSourceIpv6 = NetworkUtils.IsValidIpv6(host.IpAddress); + } + if (isTranslatedSourceNetwork) + { + var network = (CheckPoint_Network)natRule.TranslatedSource; + isTranslatedSourceIpv6 = NetworkUtils.IsValidIpv6(network.Subnet); + } + } + if (!isTranslatedSourceIpv6) + { + // translated source is not Ipv6, no sense to continue + return; + } + + // change NAT rule method + natRule.Method = CheckPoint_NAT_Rule.NatMethod.Nat46; + } + private void Add_IP_as_Host(int ciscoCommandId, string sIp) { // The order of this condition check is important!!! @@ -4053,11 +4265,11 @@ private void MatchNATRulesIntoFirewallPolicy() { continue; } - - if (cpParentRule.Source[0] is CheckPoint_PredifinedObject && cpParentRule.Source[0].Name.Equals(CheckPointObject.Any)) + + if (cpParentRule.Source[0] is CheckPoint_PredifinedObject && cpParentRule.Source[0].Name.Equals(CheckPointObject.Any)) { if (cpParentRule.SubPolicyName != GlobalRulesSubpolicyName) - { + { continue; } } @@ -4413,7 +4625,7 @@ private void Add_Optimized_Package() foreach (CheckPoint_Layer layer in regularPackage.SubPolicies) { string optimizedSubPolicyName = layer.Name + "_opt"; - + CheckPoint_Layer optimizedLayer = RuleBaseOptimizer.Optimize(layer, optimizedSubPolicyName); foreach (CheckPoint_Rule subSubRule in optimizedLayer.Rules) { @@ -4427,6 +4639,7 @@ private void Add_Optimized_Package() { regular2OptimizedLayers.Add(layer.Name, optimizedSubPolicyName); optimizedPackage.SubPolicies.Add(optimizedLayer); + validatePackage(optimizedPackage); } } @@ -4739,7 +4952,7 @@ public override void ExportPolicyPackagesAsHtml() file.WriteLine(" "); if (isSubPolicy) { - file.WriteLine(" " + + file.WriteLine(" " + string.Format(HtmlSubPolicyArrowImageTagFormat, curParentRuleId + "_img", HtmlDownArrowImageSourceData) + ruleNumber + ""); } else @@ -4752,7 +4965,7 @@ public override void ExportPolicyPackagesAsHtml() file.WriteLine(" "); if (isSubPolicy) { - file.WriteLine(" " + + file.WriteLine(" " + string.Format(HtmlSubPolicyArrowImageTagFormat, curParentRuleId + "_img", HtmlDownArrowImageSourceData) + ruleNumber + HtmlDisabledImageTag + ""); } else @@ -4794,7 +5007,7 @@ public override void ExportPolicyPackagesAsHtml() subActionStyle = subRule.Action.ToString().ToLower(); break; - case CheckPoint_Rule.ActionType.SubPolicy: + case CheckPoint_Rule.ActionType.SubPolicy: isSubSubPolicy = true; subAction = "Sub-policy: " + subRule.SubPolicyName; subActionStyle = ""; @@ -4818,16 +5031,16 @@ public override void ExportPolicyPackagesAsHtml() var sbCurRuleNumberColumnTag = new StringBuilder(); sbCurRuleNumberColumnTag.Append(" "); if (isSubSubPolicy) - { + { sbCurRuleNumberColumnTag.Append(" " + string.Format(HtmlSubPolicyArrowImageTagFormat, curRuleId + "_img", HtmlDownArrowImageSourceData) + curRuleNumber); } else - { + { sbCurRuleNumberColumnTag.Append(" "); sbCurRuleNumberColumnTag.Append(curRuleNumber); - } - + } + if (isInspectedRule) { sbCurRuleNumberColumnTag.Append(BuildInspectedRuleInfo(subRule.Tag)); @@ -4857,7 +5070,7 @@ public override void ExportPolicyPackagesAsHtml() file.WriteLine(" "); if (isSubSubPolicy) - { + { foreach (CheckPoint_Layer subSubPolicy in package.SubPolicies) { int subSubRuleNumber = 1; @@ -4866,7 +5079,7 @@ public override void ExportPolicyPackagesAsHtml() { //if (subSubRule.Layer == subRule.SubPolicyName || subSubRule.Layer == subRule.SubPolicyName + "_opt") if (subSubRule.Layer == subRule.SubPolicyName) - { + { var subRuleConversionIncidentType = ConversionIncidentType.None; string subCurRuleNumber = ruleNumber + "." + subRuleNumber + "." + subSubRuleNumber; string subCurRuleId = ruleIdPrefix + subCurRuleNumber; @@ -4921,7 +5134,7 @@ public override void ExportPolicyPackagesAsHtml() rulesWithConversionInfos.Add(subCurRuleId, subSubRule); } } - } + } } } } diff --git a/CommonUtils/IPRange.cs b/CommonUtils/IPRange.cs index e80d1671..8d6bbe0c 100644 --- a/CommonUtils/IPRange.cs +++ b/CommonUtils/IPRange.cs @@ -30,7 +30,7 @@ public class IPRange #region Constants public const string Any = "any"; - + #endregion #region Private Members @@ -39,7 +39,7 @@ public class IPRange private IPAddress _toIP; private UInt32 _minimum; private UInt32 _maximum; - + #endregion #region Properties @@ -68,7 +68,7 @@ public UInt32 Maximum _toIP = IPAddress.Parse(NetworkUtils.Number2Ip(_maximum)); } } - + #endregion #region Construction @@ -104,7 +104,7 @@ public IPRange(IPNetwork ip) _fromIP = ip.Network; _toIP = ip.Broadcast; _minimum = NetworkUtils.Ip2Number(_fromIP); - _maximum = NetworkUtils.Ip2Number(_toIP); + _maximum = NetworkUtils.Ip2Number(_toIP == null ? _fromIP : _toIP); } public IPRange(IPAddress from, IPAddress to) @@ -122,7 +122,7 @@ public IPRange(UInt32 min, UInt32 max) _minimum = min; _maximum = max; } - + #endregion #region Methods @@ -146,7 +146,7 @@ public override string ToString() { return string.Format("[{0} - {1}]", _fromIP, _toIP); } - + #endregion } @@ -158,7 +158,7 @@ public class IPRanges #region Private Members private List _ranges = null; - + #endregion #region Properties @@ -167,7 +167,7 @@ public List Ranges { get { return _ranges ?? (_ranges = new List()); } } - + #endregion #region Construction @@ -185,7 +185,7 @@ public IPRanges(List ranges) { Ranges.AddRange(ranges); } - + #endregion #region Methods @@ -329,7 +329,7 @@ public static IPRanges Negate(IPRange r1, IPRanges negatedRanges) return new IPRanges(res); } - + #endregion } } diff --git a/CommonUtils/NetworkUtils.cs b/CommonUtils/NetworkUtils.cs index 78c71daa..41de26c0 100644 --- a/CommonUtils/NetworkUtils.cs +++ b/CommonUtils/NetworkUtils.cs @@ -26,25 +26,77 @@ namespace CommonUtils /// public static class NetworkUtils { + public static bool IsValidIpv4(string sIp) + { + return IsValidIp(sIp, new AddressFamily[] { AddressFamily.InterNetwork }); + } + public static bool IsValidIpv6(string sIp) + { + return IsValidIp(sIp, new AddressFamily[] { AddressFamily.InterNetworkV6 }); + } + public static bool IsValidIp(string sIp) { + return IsValidIp(sIp, new AddressFamily[] { AddressFamily.InterNetwork, AddressFamily.InterNetworkV6 }); + } + + private static bool IsValidIp(String sIp, AddressFamily[] allowedAddressFamilies) + { + if (allowedAddressFamilies == null || allowedAddressFamilies.Length == 0) + { + return false; + } + IPAddress ip; - if (IPAddress.TryParse(sIp, out ip) && (ip.AddressFamily == AddressFamily.InterNetwork)) + if (IPAddress.TryParse(sIp, out ip) && Array.Exists(allowedAddressFamilies, e => e == ip.AddressFamily)) { return true; } - return false; } + public static bool IsValidNetmaskv4(string sNetmask) + { + return IsValidNetmask(sNetmask, new AddressFamily[] { AddressFamily.InterNetwork }); + } + + public static bool IsValidNetmaskv6(string sNetmask) + { + return IsValidNetmask(sNetmask, new AddressFamily[] { AddressFamily.InterNetworkV6 }); + } + public static bool IsValidNetmask(string sNetmask) { - IPAddress netmask; - if (IPAddress.TryParse(sNetmask, out netmask) && (netmask.AddressFamily == AddressFamily.InterNetwork)) + return IsValidNetmask(sNetmask, new AddressFamily[] { AddressFamily.InterNetwork, AddressFamily.InterNetworkV6 }); + } + + private static bool IsValidNetmask(String sNetmask, AddressFamily[] allowedAddressFamilies) + { + if (allowedAddressFamilies == null || allowedAddressFamilies.Length == 0) { - return IPNetwork.ValidNetmask(netmask); + return false; } + IPAddress netmask = null; + if (IPAddress.TryParse(sNetmask, out netmask) && Array.Exists(allowedAddressFamilies, e => e == netmask.AddressFamily)) + { + return IPNetwork.ValidNetmask(netmask); + } + return false; + } + public static bool TryParseNetwortWithPrefix(String sNetwork, out String sIp, out String sMaskLength) + { + sIp = ""; + sMaskLength = ""; + String[] splitedNetwork = sNetwork.Split('/'); + IPAddress ipAddr = null; + int maskLengthNum = 0; + if (splitedNetwork.Length == 2 && IPAddress.TryParse(splitedNetwork[0], out ipAddr) && int.TryParse(splitedNetwork[1], out maskLengthNum)) + { + sMaskLength = Convert.ToString(maskLengthNum); + sIp = Convert.ToString(ipAddr); + return true; + } return false; } @@ -158,7 +210,7 @@ public static string Number2Ip(UInt32 number) string oct1 = ((number & 0xff000000) >> 24).ToString(); string oct2 = ((number & 0x00ff0000) >> 16).ToString(); string oct3 = ((number & 0x0000ff00) >> 08).ToString(); - string oct4 = ((number & 0x000000ff) ).ToString(); + string oct4 = ((number & 0x000000ff)).ToString(); return oct1 + "." + oct2 + "." + oct3 + "." + oct4; } diff --git a/FortinetMigration/FortiGateConverter.cs b/FortinetMigration/FortiGateConverter.cs index dcfcebeb..83de468f 100644 --- a/FortinetMigration/FortiGateConverter.cs +++ b/FortinetMigration/FortiGateConverter.cs @@ -2725,6 +2725,7 @@ public void Add_ParentLayer(CheckPoint_Package package, List fgComman cpRuleLayer.Name = cpRuleZone.SubPolicyName; package.SubPolicies.Add(cpRuleLayer); + validatePackage(package); CheckPoint_Rule cpSubRuleZone = new CheckPoint_Rule(); cpSubRuleZone.Name = ""; //"intrazone_sr_" + cpZoneIntra.Name; @@ -3290,6 +3291,7 @@ public void Add_ParentLayer(CheckPoint_Package package, List fgComman cpLayer.Rules.Add(cpRuleCU); package.SubPolicies.Add(cpLayer); + validatePackage(package); } } else diff --git a/JuniperMigration/JuniperConverter.cs b/JuniperMigration/JuniperConverter.cs index 124b48e3..18bd99d8 100644 --- a/JuniperMigration/JuniperConverter.cs +++ b/JuniperMigration/JuniperConverter.cs @@ -1071,6 +1071,7 @@ private void Add_Layers_And_Rules(CheckPoint_Package package) } package.SubPolicies.Add(cpLayer); + validatePackage(package); } } @@ -1098,7 +1099,7 @@ private void Add_Global_Rules(CheckPoint_Package package) cpRule4GlobalLayer.Track = CheckPoint_Rule.TrackTypes.None; cpRule4GlobalLayer.Time.Add(_cpObjects.GetObject(CheckPointObject.Any)); cpRule4GlobalLayer.Service.Add(_cpObjects.GetObject(CheckPointObject.Any)); - cpRule4GlobalLayer.SubPolicyName = "Global Rules"; + cpRule4GlobalLayer.SubPolicyName = GlobalRulesSubpolicyName; package.ParentLayer.Rules.Add(cpRule4GlobalLayer); @@ -1108,6 +1109,7 @@ private void Add_Global_Rules(CheckPoint_Package package) cpSubLayer4GlobalRules.Name = cpRule4GlobalLayer.SubPolicyName; package.SubPolicies.Insert(0, cpSubLayer4GlobalRules); // insert at the begging becuase Global Rules should be created before all policy + validatePackage(package); foreach (var globalPolicyRule in _juniperParser.GetGlobalPolicyRules()) { @@ -1256,6 +1258,7 @@ private void Add_Global_Rules(CheckPoint_Package package) cpLayer.Tag = ","; // this info is needed later for global policy rules - in this case this sub-policy will be skipped!!! package.SubPolicies.Add(cpLayer); + validatePackage(package); // 3. Create a new rule and add to this sub-policy var cpRule = Juniper_To_CPRule(globalPolicyRule, cpLayer.Name, sourceZone, destZone); diff --git a/JuniperMigration/JuniperObjects.cs b/JuniperMigration/JuniperObjects.cs index baeab1f1..2e97fb8a 100644 --- a/JuniperMigration/JuniperObjects.cs +++ b/JuniperMigration/JuniperObjects.cs @@ -150,7 +150,7 @@ public override void Parse(XElement objectNode, string zoneName) int pos = ipPrefixText.IndexOf('/'); IpAddress = (pos == -1) ? ipPrefixText : ipPrefixText.Substring(0, pos); - if (!NetworkUtils.IsValidIp(IpAddress)) + if (!NetworkUtils.IsValidIpv4(IpAddress)) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IP address '{0}' for host object. Using IP 1.1.1.1.", IpAddress); @@ -183,7 +183,7 @@ public override void Parse(XElement objectNode, string zoneName) IpAddress = ipPrefixParts[0]; - if (!NetworkUtils.IsValidIp(IpAddress)) + if (!NetworkUtils.IsValidIpv4(IpAddress)) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IP address '{0}' for network object. Using subnet 1.1.1.0/255.255.255.0.", IpAddress); @@ -235,7 +235,7 @@ public override void Parse(XElement objectNode, string zoneName) { RangeFrom = fromNode.Value; - if (!NetworkUtils.IsValidIp(RangeFrom)) + if (!NetworkUtils.IsValidIpv4(RangeFrom)) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid starting IP range '{0}' for range object. Using IP 0.0.0.0.", RangeFrom); @@ -253,7 +253,7 @@ public override void Parse(XElement objectNode, string zoneName) { RangeTo = toNode.Value; - if (!NetworkUtils.IsValidIp(RangeTo)) + if (!NetworkUtils.IsValidIpv4(RangeTo)) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid ending IP range '{0}' for range object. Using IP 255.255.255.255.", RangeTo); @@ -336,7 +336,7 @@ public override void Parse(XElement objectNode, string zoneName) } string[] ipInfo = ipNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for interface object.", ipNode.Value); @@ -415,7 +415,7 @@ public override void Parse(XElement objectNode, string zoneName) } string[] ipInfo = ipNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for route object. Using IP 1.1.1.1.", ipNode.Value); @@ -431,7 +431,7 @@ public override void Parse(XElement objectNode, string zoneName) if (nextHopNode != null) { - if (!string.IsNullOrEmpty(nextHopNode.Value) && NetworkUtils.IsValidIp(nextHopNode.Value)) + if (!string.IsNullOrEmpty(nextHopNode.Value) && NetworkUtils.IsValidIpv4(nextHopNode.Value)) { nextHopAddress = nextHopNode.Value; } @@ -445,7 +445,7 @@ public override void Parse(XElement objectNode, string zoneName) } else if (qualifiedNextHopNode != null) { - if (!string.IsNullOrEmpty(qualifiedNextHopNode.Value) && NetworkUtils.IsValidIp(qualifiedNextHopNode.Value)) + if (!string.IsNullOrEmpty(qualifiedNextHopNode.Value) && NetworkUtils.IsValidIpv4(qualifiedNextHopNode.Value)) { nextHopAddress = qualifiedNextHopNode.Value; } @@ -974,7 +974,7 @@ protected PoolAddress ParseAddress(XElement addressNode, bool isSourceNat) } string[] ipInfo = ipNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for NAT pool object.", ipNode.Value); @@ -1014,7 +1014,7 @@ protected PoolAddress ParseAddress(XElement addressNode, bool isSourceNat) else { string[] rangeToInfo = rangeToNode.Value.Split('/'); - if (rangeToInfo.Length != 2 || !NetworkUtils.IsValidIp(rangeToInfo[0]) || rangeToInfo[1] != "32") + if (rangeToInfo.Length != 2 || !NetworkUtils.IsValidIpv4(rangeToInfo[0]) || rangeToInfo[1] != "32") { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid ending IP range '{0}' for destination NAT pool object. Using IP 255.255.255.255.", rangeToNode.Value); @@ -1056,7 +1056,7 @@ public override void Parse(XElement objectNode, string zoneName) if (hostAddressBaseNode != null && !string.IsNullOrEmpty(hostAddressBaseNode.Value)) { string[] ipInfo = hostAddressBaseNode.Value.Split('/'); - if (ipInfo.Length == 2 && NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length == 2 && NetworkUtils.IsValidIpv4(ipInfo[0])) { HostAddressBase = ipInfo[0]; } @@ -1160,7 +1160,7 @@ public override void Parse(XElement objectNode, string zoneName) foreach (var sourceAddressNode in sourceAddressNodes) { string[] ipInfo = sourceAddressNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for source NAT rule's source address object.", sourceAddressNode.Value); @@ -1191,7 +1191,7 @@ public override void Parse(XElement objectNode, string zoneName) foreach (var destAddressNode in destAddressNodes) { string[] ipInfo = destAddressNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for source NAT rule's destination address object.", destAddressNode.Value); @@ -1286,7 +1286,7 @@ public override void Parse(XElement objectNode, string zoneName) foreach (var sourceAddressNode in sourceAddressNodes) { string[] ipInfo = sourceAddressNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for destination NAT rule's source address object.", sourceAddressNode.Value); @@ -1311,7 +1311,7 @@ public override void Parse(XElement objectNode, string zoneName) foreach (var destAddressNode in destAddressNodes) { string[] ipInfo = destAddressNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for destination NAT rule's destination address object.", destAddressNode.Value); @@ -1401,7 +1401,7 @@ public override void Parse(XElement objectNode, string zoneName) foreach (var sourceAddressNode in sourceAddressNodes) { string[] ipInfo = sourceAddressNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for static NAT rule's source address object.", sourceAddressNode.Value); @@ -1436,7 +1436,7 @@ public override void Parse(XElement objectNode, string zoneName) foreach (var destAddressNode in destAddressNodes) { string[] ipInfo = destAddressNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for static NAT rule's destination address object.", destAddressNode.Value); @@ -1465,7 +1465,7 @@ public override void Parse(XElement objectNode, string zoneName) if (prefixNode != null) { string[] ipInfo = prefixNode.Value.Split('/'); - if (ipInfo.Length != 2 || !NetworkUtils.IsValidIp(ipInfo[0])) + if (ipInfo.Length != 2 || !NetworkUtils.IsValidIpv4(ipInfo[0])) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = string.Format("Invalid IPv4 address '{0}' for static NAT rule's prefix object.", prefixNode.Value); diff --git a/MigrationBase/VendorConverter.cs b/MigrationBase/VendorConverter.cs index 27224b13..5d6b6601 100644 --- a/MigrationBase/VendorConverter.cs +++ b/MigrationBase/VendorConverter.cs @@ -40,7 +40,7 @@ public abstract class VendorConverter protected const string AllInternalNetwotkGroupName = "all_internal"; protected const string AutoGeneratedNameWithError = "_Err_"; protected const string InvalidServiceNamePrefix = "service_"; - protected const string GlobalRulesSubpolicyName = "Global Rules"; + protected string GlobalRulesSubpolicyName = "Global Rules"; protected const string HtmlErrorImageTagFormat = ""; protected const string HtmlAlertImageTagFormat = ""; @@ -51,6 +51,9 @@ public abstract class VendorConverter protected const string HtmlSubPolicyArrowImageTagFormat = ""; protected const string HtmlToolLogoImageSource = "src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAgCAYAAACcuBHKAAAACXBIWXMAAAsSAAALEgHS3X78AAABkElEQVRYw+2XvXGDQBCFv/MoNx2YbEPRgZhRA+rA6sC4A7kD1IFUgdUAY9wBhJvJHeAKcMDJw2AQf5JwoBcecLx7b/exmDzPmRoP/APcSVyHRGR8IrMjMs7USjwDMZFxp7ZjDiRExp+6Jh6BDyITtN1oWnOi8HcFdJHXtXZUsQcClnnWn0RkNkBgTzUWKbBimR+rF2ZnCOwaTnVxzBoIBDUEUiABjrexIzJZyYJvK2PcKSfgo7L6yjIP+ylRbFSugW4E/qIz+fYWHUYgBbzTs6q6UlXvljmxB/xTF6jqGngH4iYidYWZ2JPM7Ya/UNUQyERkc0a1qnLrUnit7P4tShQV7NuCWtuXO6oaAy8DlHGGtWhBJLQEPOAAPPV9u6q6VtGyyv1qwvoZjyBwqCzHvWLb+l8n/2fTZqXAcoFFZX0rIkEnEqrq2BMsLtgxqYjctEWpUcAb9CkfYccJGXAQkeOoecIWZliJ8bfGnLjGoCsiO5sZX5NO2yKSAJ61YbqRX0QyEfGB7TVImPu/6J1EBT9qv6X93O05TAAAAABJRU5ErkJggg=='"; protected const string HtmlCPLogoImageSource = "src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHYAAAAUCAYAAABYm8lAAAAACXBIWXMAAAsSAAALEgHS3X78AAAHwklEQVRo3u1aaWwUZRh+tpwC7Q5Xg1KWxRhDgaYrECoe7DSgQcGw1ggKMSxREtBEy79CSLokGggkspKYEmLS5Sj+IWSbICEQZIoVoQJOQUCOyDKAIJI6WxoRsLv+6Ptt3375Zo/W/WH0TSY7813z3tes67dP6gwAfuQHKketWWFIY14AIQBLpfFGGjfpOUhXNRvLF/gAhAFE6MoWjAxzYQB2jueZRHNvQBPv659uVfsDFy786ko9Fw0GSosTPdacsAoAABWeRLYMNAC4AVwDECVEAgAWANDpMkkB/IRsvkGjdxk57hMG0SSdVU5zAaI51/OQozL4AQynewNAtaNgb8RdWLK3EO+8OwmaeyDs+EOcPduGs4fbYFkdcLsHoqxsBCyrA5bVgYa3H2YSrsaEuoq0WUCIrloSthf/LtAVXskgAQdz8AKVOVq4DLYwBEfBbmnuD9+MMaipcVa4DetNLF7yFOrqzuP8xTOZBBskoTZKQuXCDRAzZEZxzY8pGOWl8wVEaJ28JsA8QCwLhgdpn0kKly3EiMbNkpLKFizjqdOzybxXiOHB8fZK49U8lDgKdu+P/VDz2ggAwO6GK7CsDtSs7ilka/8xxOd74HYPxL0/MxIbYAJMt8bLCAMxqFzBcJ3d10vztQCWMcGp1ghm6A64RCgPaHVQxFxdfVThamU8a8mtRwivWvr1K0JalOah2IsCFRYX7nQNa+6BAICxo77H48O2YXfDFTRv2ottn57EvHkHcOfM1R6uO8v4YWbQdENyR+VEvAvABIrNfiJOJ4G10pyL3FmchKGRogjBiHOGExPKHRIVLlS9F+7Ry86N0b3fAc/6NMolhFhJe56hPR8RHyvpTOHGU7QoBdtO1ldW1mWx350uReWCjbhy7DJ27riMc+d+x6JXirFo5Uz8dHxVtoLtLXzGNJq7T40REmAuzaBxN1lqgO7Xsb02zTUpkjMh1MYchGqwKwbgKoDxxPQIw1NX4AkpjKi8isGMIiIloraUUcPRFY91J7uj8Y02nDr+S9fDoYMYrc/Gc7O2Ysqs7fB4pmLypE4sXNiJlusF+RJsNIM2QxErNWleVZrEmKXojIlutr43iUyMeZ4w4eAmJbIVtNVnSBZjigQpIyilUcIEG6o5huVvlaBmtQ+jq5dj6tzJ2LX/A3g8wwAA586/iTlzxmbzrlYFs2UIA0jmUMeNT5MdCkbmkmGL5E7kAtnu1RVXiGepafDMCzgmT6XFSdy69QceFGqoeHUiAGDl+5MAAFVVE3omUVZHtvWWiGnBDAmWwe7TQRPFLl1hsT4pvmlpGgJR1iQJsNIrkiH+ZQMmi7uqWJwXcPSfFZ4EIpFLqKt7AW5KonrE4faH+Lb5NlavbkFNTUs27xIJzFIHwYbIApty6DQZzIXKcekICclMs0YWuMlwaaX56j7y2KazxivoDmcRbnLpnmW22OD0v7Cl+SZemtaAQWNG9phrbr6dsuonipKYPS4Jv56x8xSjrLSeriATjEjp4zkyMkzrNzML9ZLyxMnibCZEkeDwNU4uNwjgB5qPKmJdLiAUrZ4lUDrLlCN9VByh5KlEzVGwJe4kNs57hBNWJ05Y93HprgsPhxThmtVBmTdw4Y4LF+64UnXv2gMDsHb2I7xR1ok0taFNzPJL9VlTL/rCNjEoLPWexVk2Uxyxxs9ifpApg8qFrvuHXLJB5YiMZyPh0JdYGyb8y7nVuuSPADfiLhy63A+HLhWg5XoBViw5iC/3zcfrVV6MGTMEG9Z38X3X5i1Ys2kxAGDFkoOp+6opndg471GqRab4CCDHQcHEvCUS/0XoEWM/PjwA+tZBMB97ErcSCcycdgvX4++hpGRolwv+5nZq7ec756Jw6H18uGw/mk9OzKVRwa3N6ENZ8T9kkxW3P3AhcrJfaqKwcACGFI6CxzMM06cOwI2LO2BZc7rbQaUxFI+M4+tjU7D/yNTUeNHgjK01jcUrHz2bUgLQCaAf29cGwGKJjihjYqwF6aXLlp55bcnHbKnmNVmnymD4mAxvTXqOKWjg9AmvZEs02rRGY++XcfVJYcnLcPZJvBkh1+opwd5kljbO/QVeDK7FqdN38dU+i8qZZ1FafA8zxnXVuKePdgt5xrgEStxJlLiTeOnpRLqsLcQ6RgGKX60swQgRch0AhtH8OvIsPzMmRhmDxJmiIa5JJUaMdYR44zwiJXBtAI6ysBCk+KWz9qXOvIzOerStUu85JGXZ49H1RUuj9Y2s1NIVuIaYgvDulMESL8EbTQprvh6CLS1OYGxREjfbXWjY8zIqWo5jUnEC659PoLQqiaJByb56B5tZl0holpGQTEkL9xABtUSkjwj0sr1RdH8cDyo8g52mPNIV+0YwpnmZ9YYY00WtbWdBg84YHWDvWobuL01mmk6T5lAGxVidHWJZu620WABoWvkgn25fYy22ICPeJI3ugPojABjT+L8rIkxTfVKvlLs/M0OpYkjuzovuT2CCWT7mMoOsXaiigYcLoRw6exbr/QoaTeq8iaZJlJVx2TRCYhnr2DyAyayumrnDpQC2A7gCoATO/2LgQtdYB8tgcY8nY2FWSkTS1Ioh5kZNhqcpWYHO6AizvVGJhrVMeFGqhePME4jS6Zqibha4CqusloQaZnW5U6PDABD6G0N6q38NHi2bAAAAAElFTkSuQmCC'"; + protected const int publishLatency = 100; + protected const int groupsMaxBulkSize = 100; + protected const int SubPoliciesMaxNumber = 249; #endregion @@ -140,6 +143,8 @@ public virtual void Initialize(VendorParser vendorParser, string vendorFilePath, _vendorFileName = Path.GetFileNameWithoutExtension(vendorFilePath); _vendorFileName = !string.IsNullOrEmpty(_vendorFileName) ? Regex.Replace(_vendorFileName, @"\s+", "_") : ""; + GlobalRulesSubpolicyName = _vendorFileName + "_Global Rules"; + // policy package names _policyPackageName = _vendorFileName + "_policy"; _policyPackageOptimizedName = _vendorFileName + "_policy_opt"; @@ -842,7 +847,6 @@ protected IPRanges GetGroupWithExclusionRanges(CheckPoint_NetworkGroup includeGr protected void CreateObjectsScript() { - const int publishLatency = 100; using (var file = new StreamWriter(ObjectsScriptFile, false)) { @@ -978,12 +982,32 @@ protected void CreateObjectsScript() continue; } - file.WriteLine(CLIScriptBuilder.GenerateObjectScript(obj)); + //if a group has no members + if (obj.Members.Count == 0) + { + file.WriteLine(CLIScriptBuilder.GenerateObjectScript(obj)); - objectsCount++; - if (objectsCount % publishLatency == 0) + objectsCount++; + if (objectsCount % publishLatency == 0) + { + file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); + } + continue; + } + + //if a group has more then max size for publish - generate part of group divided by small groups. + obj.MembersMaxPublishSize = groupsMaxBulkSize; + for (int i = 0; i < obj.Members.Count; i += groupsMaxBulkSize) { - file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); + obj.MembersPublishIndex = i; + + file.WriteLine(CLIScriptBuilder.GenerateObjectScript(obj)); + + objectsCount++; + if (objectsCount % publishLatency == 0) + { + file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); + } } } file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); @@ -1181,12 +1205,32 @@ protected void CreateObjectsScript() int objectsCount = 0; foreach (CheckPoint_ServiceGroup obj in _cpServiceGroups) { - file.WriteLine(CLIScriptBuilder.GenerateObjectScript(obj)); + //if a group has no members + if (obj.Members.Count == 0) + { + file.WriteLine(CLIScriptBuilder.GenerateObjectScript(obj)); - objectsCount++; - if (objectsCount % publishLatency == 0) + objectsCount++; + if (objectsCount % publishLatency == 0) + { + file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); + } + continue; + } + + //if a group has more then max size for publish - generate part of group divided by small groups. + obj.MembersMaxPublishSize = groupsMaxBulkSize; + for (int i = 0; i < obj.Members.Count; i += groupsMaxBulkSize) { - file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); + obj.MembersPublishIndex = i; + + file.WriteLine(CLIScriptBuilder.GenerateObjectScript(obj)); + + objectsCount++; + if (objectsCount % publishLatency == 0) + { + file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); + } } } file.WriteLine(CLIScriptBuilder.GeneratePublishScript()); @@ -1245,7 +1289,7 @@ protected void CreateObjectsScript() if (_cpAccessRoles.Count > 0) { - file.WriteLine("if [ $NUSE -ne 0 ]; then"); + file.WriteLine("if [[ $NUSE -ne 0 ]]; then"); file.WriteLine(" " + CLIScriptBuilder.GenerateInstructionScript(string.Format("Create {0} Objects (x{1}) ", "Access Role", _cpAccessRoles.Count))); int objectsCount = 0; @@ -1308,6 +1352,14 @@ protected void CreateObjectsScript() } } + protected void validatePackage(CheckPoint_Package package) + { + if (package != null && package.SubPolicies != null && package.SubPolicies.Count > SubPoliciesMaxNumber) + { + throw new InvalidDataException("Policy exceeds the maximum number of supported policy layers."); + } + } + protected void CreatePackagesScript() { const int publishLatency = 100; @@ -1315,6 +1367,7 @@ protected void CreatePackagesScript() foreach (CheckPoint_Package package in _cpPackages) { + validatePackage(package); ++packageNumber; string filename = _targetFolder + "\\" + package.Name + ".sh"; @@ -1461,9 +1514,25 @@ protected void CreateObjectsHtml() file.WriteLine("

{0} Objects (x{1})

", "Network Groups", _cpNetworkGroups.Count()); foreach (CheckPoint_NetworkGroup obj in _cpNetworkGroups) { - file.WriteLine("
"); - file.WriteLine(obj.ToCLIScript()); - file.WriteLine("
"); + if (obj.Members.Count > groupsMaxBulkSize) + { + obj.MembersMaxPublishSize = groupsMaxBulkSize; + for (int i = 0; i < obj.Members.Count; i += groupsMaxBulkSize) + { + file.WriteLine("
"); + + obj.MembersPublishIndex = i; + file.WriteLine(obj.ToCLIScript()); + + file.WriteLine("
"); + } + } + else + { + file.WriteLine("
"); + file.WriteLine(obj.ToCLIScript()); + file.WriteLine("
"); + } } file.WriteLine("

{0} Objects (x{1})

", "Groups with exclusion", _cpGroupsWithExclusion.Count()); @@ -1549,9 +1618,25 @@ protected void CreateObjectsHtml() file.WriteLine("

{0} Objects (x{1})

", "Service Groups", _cpServiceGroups.Count()); foreach (CheckPoint_ServiceGroup obj in _cpServiceGroups) { - file.WriteLine("
"); - file.WriteLine(obj.ToCLIScript()); - file.WriteLine("
"); + if (obj.Members.Count > groupsMaxBulkSize) + { + obj.MembersMaxPublishSize = groupsMaxBulkSize; + for (int i = 0; i < obj.Members.Count; i += groupsMaxBulkSize) + { + file.WriteLine("
"); + + obj.MembersPublishIndex = i; + file.WriteLine(obj.ToCLIScript()); + + file.WriteLine("
"); + } + } + else + { + file.WriteLine("
"); + file.WriteLine(obj.ToCLIScript()); + file.WriteLine("
"); + } } file.WriteLine("

{0} Objects (x{1})

", "Application Groups", _cpApplicationGroups.Count()); diff --git a/NetScreenMigration/ScreenOSCommands.cs b/NetScreenMigration/ScreenOSCommands.cs index a21f6efb..f43645f3 100644 --- a/NetScreenMigration/ScreenOSCommands.cs +++ b/NetScreenMigration/ScreenOSCommands.cs @@ -253,7 +253,7 @@ public bool IsWildCardMask { get { - if (string.IsNullOrEmpty(_mask) || NetworkUtils.IsValidNetmask(_mask)) + if (string.IsNullOrEmpty(_mask) || NetworkUtils.IsValidNetmaskv4(_mask)) { return false; } @@ -319,7 +319,7 @@ public override void Parse(ScreenOSCommand command) ObjectName = command.GetParam(3); string commandParam = command.GetParam(5); - if (NetworkUtils.IsValidNetmask(commandParam) || NetworkUtils.IsWildCardNetmask(commandParam)) + if (NetworkUtils.IsValidNetmaskv4(commandParam) || NetworkUtils.IsWildCardNetmask(commandParam)) { Netmask = commandParam; if (NetworkUtils.GetMaskLength(Netmask) == 32) @@ -333,7 +333,7 @@ public override void Parse(ScreenOSCommand command) IpAddress = NetworkUtils.GetNetwork(command.GetParam(4), Netmask); } } - else if (NetworkUtils.IsValidIp(commandParam)) + else if (NetworkUtils.IsValidIpv4(commandParam)) { // Complex wild card not supported, e.g 0.255.0.255 AddressType = AddressTypeEnum.Network; @@ -675,8 +675,8 @@ public override void Parse(ScreenOSCommand command) IpAddressFirst = command.GetParam(3); IpAddressLast = command.GetParam(4); - if (!NetworkUtils.IsValidIp(IpAddressFirst) || - !NetworkUtils.IsValidIp(IpAddressLast) || + if (!NetworkUtils.IsValidIpv4(IpAddressFirst) || + !NetworkUtils.IsValidIpv4(IpAddressLast) || NetworkUtils.Ip2Number(IpAddressLast) < NetworkUtils.Ip2Number(IpAddressFirst)) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; @@ -917,7 +917,7 @@ public override void Parse(ScreenOSCommand command) } else if (commandParam.Length == 1) { - if (NetworkUtils.IsValidIp(commandParam[0])) + if (NetworkUtils.IsValidIpv4(commandParam[0])) { IP = commandParam[0]; Mask = command.GetParam(5); @@ -1024,7 +1024,7 @@ public override void Parse(ScreenOSCommand command) Network = commandParam[0]; Mask = NetworkUtils.MaskLength2Netmask(int.Parse(commandParam[1])); - if (!NetworkUtils.IsValidIp(Network)) + if (!NetworkUtils.IsValidIpv4(Network)) { ConversionIncidentType = ConversionIncidentType.ManualActionRequired; ConversionIncidentMessage = "ScreenOS route object network or mask is invalid. Ignoring this command"; @@ -1325,7 +1325,7 @@ private PolicyNatTypeEnum ParseNatPart(ScreenOSCommand command, ref int baseInde DestNatIp.Add(commandString); commandString = command.GetParam(++baseIndex); - if (NetworkUtils.IsValidIp(commandString)) + if (NetworkUtils.IsValidIpv4(commandString)) { DestNatIp.Add(commandString); commandString = command.GetParam(++baseIndex); @@ -1534,7 +1534,7 @@ public override void Parse(ScreenOSCommand command) // Get Mip string commandParam = command.GetParam(++paramIndex); - if (NetworkUtils.IsValidIp(commandParam)) + if (NetworkUtils.IsValidIpv4(commandParam)) { Mip = commandParam; } @@ -1548,7 +1548,7 @@ public override void Parse(ScreenOSCommand command) // Get IP paramIndex += 2; commandParam = command.GetParam(paramIndex); - if (NetworkUtils.IsValidIp(commandParam)) + if (NetworkUtils.IsValidIpv4(commandParam)) { Ip = commandParam; } @@ -1562,7 +1562,7 @@ public override void Parse(ScreenOSCommand command) // Get Mask paramIndex += 2; commandParam = command.GetParam(paramIndex); - if (NetworkUtils.IsValidNetmask(commandParam)) + if (NetworkUtils.IsValidNetmaskv4(commandParam)) { Mask = commandParam; } diff --git a/NetScreenMigration/ScreenOSConverter.cs b/NetScreenMigration/ScreenOSConverter.cs index d3068804..d30cc12b 100644 --- a/NetScreenMigration/ScreenOSConverter.cs +++ b/NetScreenMigration/ScreenOSConverter.cs @@ -51,19 +51,19 @@ public class ScreenOSNetworkUtil public static bool IsMask(string maskLength) { int n; - return (int.TryParse(maskLength, out n) && NetworkUtils.IsValidNetmask(NetworkUtils.MaskLength2Netmask(n))); + return (int.TryParse(maskLength, out n) && NetworkUtils.IsValidNetmaskv4(NetworkUtils.MaskLength2Netmask(n))); } public static bool IsHost(string host) { string[] hostArray = host.Split('/'); - return (hostArray.Length == 2 && NetworkUtils.IsValidIp(hostArray[0]) && IsMask(hostArray[1]) && int.Parse(hostArray[1]) == 32); + return (hostArray.Length == 2 && NetworkUtils.IsValidIpv4(hostArray[0]) && IsMask(hostArray[1]) && int.Parse(hostArray[1]) == 32); } public static bool IsNetwork(string host) { string[] hostArray = host.Split('/'); - return (hostArray.Length == 2 && NetworkUtils.IsValidIp(hostArray[0]) && IsMask(hostArray[1]) && int.Parse(hostArray[1]) < 32); + return (hostArray.Length == 2 && NetworkUtils.IsValidIpv4(hostArray[0]) && IsMask(hostArray[1]) && int.Parse(hostArray[1]) < 32); } public static bool IsIPv6(string ip) @@ -1250,7 +1250,7 @@ private CheckPointObject GetCheckPointObjByIpRange(string startIp, string endIp, return cpRange; } - private CheckPointObject GetSrcObjectByNameFromPolicy(string srcName, PolicyCommandSimplifier policy, bool isNAT= false) + private CheckPointObject GetSrcObjectByNameFromPolicy(string srcName, PolicyCommandSimplifier policy, bool isNAT = false) { CheckPointObject cpObject; string sourceName = srcName; @@ -1311,7 +1311,7 @@ private CheckPointObject GetSrcObjectFromPolicyForNAT(PolicyCommandSimplifier po } else { - srcOrig = GetSrcObjectByNameFromPolicy(policy.SrcAddr.First(), policy,true); + srcOrig = GetSrcObjectByNameFromPolicy(policy.SrcAddr.First(), policy, true); } return srcOrig; @@ -2366,6 +2366,7 @@ private void Add_IntraZoneRules(CheckPoint_Package package) cpLayer.Value.Rules.Add(cpInterBlockRule); package.SubPolicies.Add(cpLayer.Value); + validatePackage(package); } } @@ -2424,6 +2425,7 @@ private void Add_InterZoneRules(CheckPoint_Package package) cpLayer.Rules.Add(cpCleanupRule); package.SubPolicies.Add(cpLayer); + validatePackage(package); } } @@ -3503,6 +3505,7 @@ private void Add_NatPolicy2RegularPolicy() } cpLayer.Rules.Last().Name = "Sub-Policy Cleanup rule"; _cpPackages[0].SubPolicies.Insert(firstGlobal,cpLayer); + validatePackage(_cpPackages[0]); } } } diff --git a/PaloAltoMigration/PaloAltoConverter.cs b/PaloAltoMigration/PaloAltoConverter.cs index 5a7ffd34..e1bb6e4e 100644 --- a/PaloAltoMigration/PaloAltoConverter.cs +++ b/PaloAltoMigration/PaloAltoConverter.cs @@ -2584,6 +2584,7 @@ public void ConvertSecurityPolicy(PA_VsysEntry paVsysEntry, cpLayer.ApplicationsAndUrlFiltering = false; cpPackage.SubPolicies.Add(cpLayer); + validatePackage(cpPackage); CheckPoint_Rule cpGroupRule = new CheckPoint_Rule(); cpGroupRule.Name = cpGroupRuleName; diff --git a/PaloAltoMigration/PanoramaConverter.cs b/PaloAltoMigration/PanoramaConverter.cs index 36016eb4..3010ec75 100644 --- a/PaloAltoMigration/PanoramaConverter.cs +++ b/PaloAltoMigration/PanoramaConverter.cs @@ -2873,6 +2873,7 @@ Dictionary _devicesUIDDict cpLayer.ApplicationsAndUrlFiltering = false; cpPackage.SubPolicies.Add(cpLayer); + validatePackage(cpPackage); CheckPoint_Rule cpGroupRule = new CheckPoint_Rule(); cpGroupRule.Name = cpGroupRuleName; diff --git a/SmartMove/CommandLine.cs b/SmartMove/CommandLine.cs index ed624fca..725ea214 100644 --- a/SmartMove/CommandLine.cs +++ b/SmartMove/CommandLine.cs @@ -513,8 +513,17 @@ public void DoMigration(CommandLine commandLine) } catch (Exception ex) { - - Console.WriteLine(string.Format("Could not convert configuration file.\n\nMessage: {0}\nModule:\t{1}\nClass:\t{2}\nMethod:\t{3}", ex.Message, ex.Source, ex.TargetSite.ReflectedType.Name, ex.TargetSite.Name), MessageTypes.Error); + + if (ex is InvalidDataException && ex.Message != null && ex.Message.Contains("Policy exceeds the maximum number")) + { + Console.WriteLine(String.Format("{1}{0}{2}{0}{3}", Environment.NewLine, "SmartMove is unable to convert the provided policy.", + "Reason: Policy exceeds the maximum number of supported policy layers.", + "To assure the smooth conversion of your data, it is recommended to contact Check Point Professional Services by sending an e-mail to ps@checkpoint.com")); + } + else + { + Console.WriteLine(string.Format("Could not convert configuration file.\n\nMessage: {0}\nModule:\t{1}\nClass:\t{2}\nMethod:\t{3}", ex.Message, ex.Source, ex.TargetSite.ReflectedType.Name, ex.TargetSite.Name), MessageTypes.Error); + } return; } diff --git a/SmartMove/MainWindow.xaml.cs b/SmartMove/MainWindow.xaml.cs index 0365276a..95a741ca 100644 --- a/SmartMove/MainWindow.xaml.cs +++ b/SmartMove/MainWindow.xaml.cs @@ -621,7 +621,17 @@ private async void Go_OnClick(object sender, RoutedEventArgs e) Mouse.OverrideCursor = null; EnableDisableControls(true); OutputPanel.Visibility = Visibility.Collapsed; - ShowMessage(string.Format("Could not convert configuration file.\n\nMessage: {0}\nModule:\t{1}\nClass:\t{2}\nMethod:\t{3}", ex.Message, ex.Source, ex.TargetSite.ReflectedType.Name, ex.TargetSite.Name), MessageTypes.Error); + if (ex is InvalidDataException && ex.Message != null && ex.Message.Contains("Policy exceeds the maximum number")) + { + ShowMessage(String.Format("{1}{0}{2}{0}{3}", Environment.NewLine, "SmartMove is unable to convert the provided policy.", + "Reason: Policy exceeds the maximum number of supported policy layers.", + "To assure the smooth conversion of your data, it is recommended to contact Check Point Professional Services by sending an e-mail to"), + MessageTypes.Error, "ps@checkpoint.com", "mailto:ps@checkpoint.com"); + } + else + { + ShowMessage(string.Format("Could not convert configuration file.\n\nMessage: {0}\nModule:\t{1}\nClass:\t{2}\nMethod:\t{3}", ex.Message, ex.Source, ex.TargetSite.ReflectedType.Name, ex.TargetSite.Name), MessageTypes.Error); + } return; } diff --git a/SmartMove/SmartConnector/smartconnector.py b/SmartMove/SmartConnector/smartconnector.py index 02396be9..f68437c0 100644 --- a/SmartMove/SmartConnector/smartconnector.py +++ b/SmartMove/SmartConnector/smartconnector.py @@ -4,6 +4,9 @@ import argparse import json import os +import re +import operator +import uuid sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '.'))) from cpapi import APIClient, APIClientArgs @@ -93,6 +96,8 @@ def isIpDuplicated(res_add_obj): messagePrefixes = ("Multiple objects have the same IP address",) messagePrefixes += ("More than one network have the same IP",) messagePrefixes += ("More than one network has the same IP",) + messagePrefixes += ("More than one object have the same IPv6",) + messagePrefixes += ("More than one object has the same IPv6",) for msg in res_add_obj.data['warnings']: if msg['message'].startswith(messagePrefixes): isIpDuplicated = True @@ -169,22 +174,24 @@ def addCpObjectWithIpToServer(client, payload, userObjectType, userObjectIp, mer printStatus(res_add_obj_with_ip, "REPORT: " + userObjectNameInitial + " is added as " + payload['name']) if res_add_obj_with_ip.success is False: if isIpDuplicated(res_add_obj_with_ip) and not isIgnoreWarnings: - res_get_obj_with_ip = client.api_query("show-objects", payload={"filter": userObjectIp, "ip-only": True, - "type": userObjectType}) + res_get_obj_with_ip = client.api_query("show-objects", payload={"filter": userObjectIp, "ip-only": True, "type": userObjectType}) printStatus(res_get_obj_with_ip, None) if res_get_obj_with_ip.success is True: if len(res_get_obj_with_ip.data) > 0: - for serverObject in res_get_obj_with_ip.data: - if isServerObjectLocal(serverObject) and not isReplaceFromGlobalFirst: + if userObjectType == "network" and next((x for x in res_get_obj_with_ip.data if x['subnet4' if is_valid_ipv4(payload['subnet']) else 'subnet6'] == payload['subnet']), None) is None: + isIgnoreWarnings = True + else: + if userObjectType == "host": + mergedObjectsNamesMap[userObjectNameInitial] = res_get_obj_with_ip.data[0]['name'] + printStatus(None, "REPORT: " + "CP object " + mergedObjectsNamesMap[userObjectNameInitial] + " is used instead of " + userObjectNameInitial) + isFinished = True + break + for serverObject in res_get_obj_with_ip.data: mergedObjectsNamesMap[userObjectNameInitial] = serverObject['name'] - break - if isServerObjectGlobal(serverObject) and isReplaceFromGlobalFirst: - mergedObjectsNamesMap[userObjectNameInitial] = serverObject['name'] - break - mergedObjectsNamesMap[userObjectNameInitial] = serverObject['name'] - printStatus(None, "REPORT: " + "CP object " + mergedObjectsNamesMap[ - userObjectNameInitial] + " is used instead of " + userObjectNameInitial) - isFinished = True + if (isServerObjectLocal(serverObject) and not isReplaceFromGlobalFirst) or (isServerObjectGlobal(serverObject) and isReplaceFromGlobalFirst): + break + printStatus(None, "REPORT: " + "CP object " + mergedObjectsNamesMap[userObjectNameInitial] + " is used instead of " + userObjectNameInitial) + isFinished = True else: isIgnoreWarnings = True else: @@ -209,22 +216,34 @@ def addCpObjectWithIpToServer(client, payload, userObjectType, userObjectIp, mer # mergedGroupsNamesMap - the map which contains name of user's object (key) and name of resulting object (value) # --- # returns: updated mergedGroupsNamesMap -def processGroupWithMembers(client, apiCommand, userGroup, mergedObjectsMap, mergedGroupsNamesMap): - for i, userGroupMember in enumerate(userGroup['Members']): - if userGroupMember in mergedObjectsMap: - userGroup['Members'][i] = mergedObjectsMap[userGroupMember] - elif userGroupMember in mergedGroupsNamesMap: - userGroup['Members'][i] = mergedGroupsNamesMap[userGroupMember] - addedGroup = addUserObjectToServer( - client, - apiCommand, - { +def processGroupWithMembers(client, apiCommand, userGroup, mergedObjectsMap, mergedGroupsNamesMap, isNeedSplitted): + apiSetCommand = "set-group" + addedGroup = None + if "time" in apiCommand: + apiSetCommand = "set-time-group" + elif "service" in apiCommand: + apiSetCommand = "set-service-group" + + if isNeedSplitted: + for i, userGroupMember in enumerate(userGroup['Members']): + print(userGroupMember) + res_add_obj = client.api_call( + apiSetCommand, + { + "name": userGroup['Name'], + "members": { "add" : userGroupMember } + }) + printStatus(None, "REPORT: " + userGroup['Name'] + " is setted with new member " + str(userGroupMember)) + else: + addedGroup = addUserObjectToServer( + client, + apiCommand, + { "name": userGroup['Name'], - "members": userGroup['Members'], "comments": userGroup['Comments'], "tags": userGroup['Tags'] - } - ) + } + ) return addedGroup @@ -298,6 +317,72 @@ def processHosts(client, userHosts): return mergedHostsNamesMap +def is_valid_ipv4(ip): + pattern = re.compile(r""" + ^ + (?: + # Dotted variants: + (?: + # Decimal 1-255 (no leading 0's) + [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2} + | + 0x0*[0-9a-f]{1,2} # Hexadecimal 0x0 - 0xFF (possible leading 0's) + | + 0+[1-3]?[0-7]{0,2} # Octal 0 - 0377 (possible leading 0's) + ) + (?: # Repeat 0-3 times, separated by a dot + \. + (?: + [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2} + | + 0x0*[0-9a-f]{1,2} + | + 0+[1-3]?[0-7]{0,2} + ) + ){0,3} + | + 0x0*[0-9a-f]{1,8} # Hexadecimal notation, 0x0 - 0xffffffff + | + 0+[0-3]?[0-7]{0,10} # Octal notation, 0 - 037777777777 + | + # Decimal notation, 1-4294967295: + 429496729[0-5]|42949672[0-8]\d|4294967[01]\d\d|429496[0-6]\d{3}| + 42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}| + 4[01]\d{8}|[1-3]\d{0,9}|[4-9]\d{0,8} + ) + $ + """, re.VERBOSE | re.IGNORECASE) + return pattern.match(ip) is not None + +def is_valid_ipv6(ip): + pattern = re.compile(r""" + ^ + \s* # Leading whitespace + (?!.*::.*::) # Only a single whildcard allowed + (?:(?!:)|:(?=:)) # Colon iff it would be part of a wildcard + (?: # Repeat 6 times: + [0-9a-f]{0,4} # A group of at most four hexadecimal digits + (?:(?<=::)|(?_ # if network contains existing IP subnet then Network object from server will be used instead @@ -310,19 +395,22 @@ def processNetworks(client, userNetworks): printMessageProcessObjects("networks") publishCounter = 0 mergedNetworksNamesMap = {} + userNetworks = sorted(userNetworks, key=lambda K: (K['Netmask'], K['MaskLength']) , reverse=True) if len(userNetworks) == 0: return mergedNetworksNamesMap for userNetwork in userNetworks: payload = { "name": userNetwork['Name'], - "subnet4": userNetwork['Subnet'], - "subnet-mask": userNetwork['Netmask'], "comments": userNetwork['Comments'], - "tags": userNetwork['Tags'] + "tags": userNetwork['Tags'], + "subnet": userNetwork['Subnet'] } + if is_valid_ipv4(userNetwork['Subnet']): + payload["subnet-mask"] = userNetwork['Netmask'] + else: + payload["mask-length6"] = userNetwork['MaskLength'] initialMapLength = len(mergedNetworksNamesMap) - mergedNetworksNamesMap = addCpObjectWithIpToServer(client, payload, "network", userNetwork['Subnet'], - mergedNetworksNamesMap) + mergedNetworksNamesMap = addCpObjectWithIpToServer(client, payload, "network", userNetwork['Subnet'], mergedNetworksNamesMap) if initialMapLength == len(mergedNetworksNamesMap): printStatus(None, "REPORT: " + userNetwork['Name'] + ' is not added.') else: @@ -332,6 +420,7 @@ def processNetworks(client, userNetworks): return mergedNetworksNamesMap + # processing and adding to server the CheckPoint Ranges # adjusting the name if range with the name exists at server: _ # if range contains existing IP start and end then Range object from server will be used instead @@ -354,12 +443,16 @@ def processRanges(client, userRanges): printStatus(res_get_ranges, None) for serverRange in res_get_ranges.data: key = serverRange['ipv4-address-first'] + '_' + serverRange['ipv4-address-last'] + if serverRange['ipv4-address-first'] == "": + key = serverRange['ipv6-address-first'] + '_' + serverRange['ipv6-address-last'] + if isServerObjectGlobal(serverRange) and key not in serverRangesMapGlobal: serverRangesMapGlobal[key] = serverRange['name'] elif isServerObjectLocal(serverRange) and key not in serverRangesMapLocal: serverRangesMapLocal[key] = serverRange['name'] elif key not in serverRangesMapGlobal and key not in serverRangesMapLocal and key not in serverRangesMap: serverRangesMap[key] = serverRange['name'] + printStatus(None, "") if sys.version_info >= (3, 0): serverRangesMap = serverRangesMap.copy() @@ -406,6 +499,8 @@ def processRanges(client, userRanges): if addedRange is not None: mergedRangesNamesMap[userRangeNameInitial] = addedRange['name'] key = addedRange['ipv4-address-first'] + '_' + addedRange['ipv4-address-last'] + if addedRange['ipv4-address-first'] == "": + key = addedRange['ipv6-address-first'] + '_' + addedRange['ipv6-address-last'] serverRangesMap[key] = addedRange['name'] printStatus(None, "REPORT: " + userRangeNameInitial + " is added as " + addedRange['name']) publishCounter = publishUpdate(publishCounter, False) @@ -453,11 +548,13 @@ def processNetGroups(client, userNetworkGroups, mergedNetworkObjectsMap): else: printStatus(None, "processing network group: " + userNetworkGroup['Name']) addedNetworkGroup = processGroupWithMembers(client, "add-group", userNetworkGroup, mergedNetworkObjectsMap, - mergedGroupsNamesDict) + mergedGroupsNamesDict, False) if addedNetworkGroup is not None: mergedGroupsNamesDict[userNetworkGroupNameInitial] = addedNetworkGroup['name'] printStatus(None, "REPORT: " + userNetworkGroupNameInitial + " is added as " + addedNetworkGroup['name']) - publishCounter = publishUpdate(publishCounter, False) + publishCounter = publishUpdate(publishCounter, True) + userNetworkGroup["Name"] = addedNetworkGroup['name'] + processGroupWithMembers(client, "add-group", userNetworkGroup, mergedNetworkObjectsMap, mergedGroupsNamesDict, True) else: printStatus(None, "REPORT: " + userNetworkGroupNameInitial + " is not added.") printStatus(None, "") @@ -685,11 +782,13 @@ def processServicesGroups(client, userServicesGroups, mergedServicesMap): printStatus(None, "processing services group: " + userServicesGroup['Name']) userServicesGroupNameInitial = userServicesGroup['Name'] addedServicesGroup = processGroupWithMembers(client, "add-service-group", userServicesGroup, mergedServicesMap, - mergedServicesGroupsNamesMap) + mergedServicesGroupsNamesMap, False) if addedServicesGroup is not None: mergedServicesGroupsNamesMap[userServicesGroupNameInitial] = addedServicesGroup['name'] printStatus(None, "REPORT: " + userServicesGroupNameInitial + " is added as " + addedServicesGroup['name']) - publishCounter = publishUpdate(publishCounter, False) + publishCounter = publishUpdate(publishCounter, True) + userServicesGroup["Name"] = addedServicesGroup['name'] + processGroupWithMembers(client, "add-service-group", userServicesGroup, mergedServicesMap, mergedServicesGroupsNamesMap, True) else: printStatus(None, "REPORT: " + userServicesGroupNameInitial + " is not added.") printStatus(None, "") @@ -701,10 +800,11 @@ def processServicesGroups(client, userServicesGroups, mergedServicesMap): # adjusting the name if time group with the name exists at server: _ # client - client object # userTimesGroups - the list of time groups which will be processed and added to server +# mergedTimesNamesMap - the list of the time names # --- # returns: mergedTimesGroupsNamesMap dictionary # the map contains name of user's object (key) and name of resulting object (value) -def processTimesGroups(client, userTimesGroups): +def processTimesGroups(client, userTimesGroups, mergedTimesNamesMap): printMessageProcessObjects("times groups") publishCounter = 0 mergedTimesGroupsNamesMap = {} @@ -713,20 +813,14 @@ def processTimesGroups(client, userTimesGroups): for userTimesGroup in userTimesGroups: printStatus(None, "processing times group: " + userTimesGroup['Name']) userTimesGroupNameInitial = userTimesGroup['Name'] - addedTimesGroup = addUserObjectToServer( - client, - "add-time-group", - { - "name": userTimesGroup['Name'], - "members": userTimesGroup['Members'], - "comments": userTimesGroup['Comments'], - "tags": userTimesGroup['Tags'] - } - ) + addedTimesGroup = processGroupWithMembers(client, "add-time-group", userTimesGroup, mergedTimesNamesMap, + mergedTimesGroupsNamesMap, False) if addedTimesGroup is not None: mergedTimesGroupsNamesMap[userTimesGroupNameInitial] = addedTimesGroup['name'] printStatus(None, "REPORT: " + userTimesGroupNameInitial + " is added as " + addedTimesGroup['name']) - publishCounter = publishUpdate(publishCounter, False) + publishCounter = publishUpdate(publishCounter, True) + userTimesGroup["Name"] = addedTimesGroup['name'] + processGroupWithMembers(client, "add-time-group", userTimesGroup, mergedTimesNamesMap, mergedTimesGroupsNamesMap, True) else: printStatus(None, "REPORT: " + userTimesGroupNameInitial + ' is not added.') printStatus(None, "") @@ -924,8 +1018,11 @@ def addAccessRules(client, userRules, userLayerName, skipCleanUpRule, mergedNetw def processPackage(client, userPackage, mergedNetworkObjectsMap, mergedServiceObjectsMap, mergedTimesGroupsNamesMap, mergedTimesNamesMap): printMessageProcessObjects("package") + allExistingLayers = {} addedPackage = None if userPackage is not None: + original_package_name = userPackage['Name'] + userPackage['Name'] = userPackage['Name'] + "_" + str(uuid.uuid4().hex[:3].upper()) publishCounter = 0 printStatus(None, "processing package: " + userPackage['Name']) addedPackage = addUserObjectToServer( @@ -946,7 +1043,15 @@ def processPackage(client, userPackage, mergedNetworkObjectsMap, mergedServiceOb publishCounter = publishUpdate(publishCounter, True) if userPackage['SubPolicies'] is not None: for userSubLayer in userPackage['SubPolicies']: + originalName = userSubLayer['Name'] + userSubLayer['Name'] = userSubLayer['Name'] + "_" + str(uuid.uuid4().hex[:3].upper()) + allExistingLayers[originalName] = userSubLayer['Name'] + for rule in userSubLayer['Rules']: + rule['Layer'] = userSubLayer['Name'] + if rule['SubPolicyName'] != "": + rule['SubPolicyName'] = allExistingLayers[rule['SubPolicyName']] printStatus(None, "processing access layer: " + userSubLayer['Name']) + addedSubLayer = addUserObjectToServer( client, "add-access-layer", @@ -968,10 +1073,26 @@ def processPackage(client, userPackage, mergedNetworkObjectsMap, mergedServiceOb addAccessRules(client, userSubLayer['Rules'], userSubLayer['Name'], False, mergedNetworkObjectsMap, mergedServiceObjectsMap, mergedTimesGroupsNamesMap, mergedTimesNamesMap) if userPackage['ParentLayer'] is not None: + userPackage['ParentLayer']['Name'] = userPackage['ParentLayer']['Name'].replace(original_package_name, userPackage['Name']) + for parentRule in userPackage['ParentLayer']['Rules']: + parentRule['Layer'] = userPackage['ParentLayer']['Name'] + if parentRule['SubPolicyName'] != "": + parentRule['SubPolicyName'] = allExistingLayers[parentRule['SubPolicyName']] addAccessRules(client, userPackage['ParentLayer']['Rules'], "parent", True, mergedNetworkObjectsMap, mergedServiceObjectsMap, mergedTimesGroupsNamesMap, mergedTimesNamesMap) return addedPackage +# resolver for nat method type +# typeValue - number of type [ static, hide, nat64, nat46 ] +def getMethodType(typeValue): + _type = "static" + if typeValue == 1: + _type = "hide" + elif typeValue == 2: + _type = "nat64" + elif typeValue == 3: + _type = "nat46" + return _type # processing and adding to server the CheckPoint NAT rules # NAT rules are added if package has been added @@ -989,6 +1110,7 @@ def processNatRules(client, addedPackage, userNatRules, mergedNetworkObjectsMap, return publishCounter = 0 for i, userNatRule in enumerate(userNatRules): + userNatRule['Package'] = addedPackage['name'] printStatus(None, "processing nat rule: #" + str(i)) sourceOrig = "" if userNatRule['Source'] is not None: @@ -1024,7 +1146,7 @@ def processNatRules(client, addedPackage, userNatRules, mergedNetworkObjectsMap, "position": "bottom", "comments": userNatRule['Comments'], "enabled": userNatRule['Enabled'], - "method": "static" if userNatRule['Method'] == 0 else "hide", + "method": getMethodType(userNatRule['Method']), "original-source": sourceOrig, "original-destination": destinationOrig, "original-service": serviceOrig, @@ -1234,8 +1356,8 @@ def processNatRules(client, addedPackage, userNatRules, mergedNetworkObjectsMap, mergedServicesObjectsMap.update(processServices(client, userServicesOther, "other")) mergedServicesObjectsMap.update( processServicesGroups(client, userServicesGroups, mergedServicesObjectsMap)) - mergedTimesGroupsMap = processTimesGroups(client, userTimesGroups) mergedTimesMap = processTimes(client, userTimes) + mergedTimesGroupsMap = processTimesGroups(client, userTimesGroups, mergedTimesMap) addedPackage = processPackage(client, userPackage, mergedNetworkObjectsMap, mergedServicesObjectsMap, mergedTimesGroupsMap, mergedTimesMap) processNatRules(client, addedPackage, userNatRules, mergedNetworkObjectsMap, mergedServicesObjectsMap) diff --git a/SmartMove/SmartMove.csproj b/SmartMove/SmartMove.csproj index 8b7dbdf7..8f88ad71 100644 --- a/SmartMove/SmartMove.csproj +++ b/SmartMove/SmartMove.csproj @@ -38,6 +38,7 @@ DEBUG;TRACE prompt 4 + 6 AnyCPU @@ -143,7 +144,7 @@ ResXFileCodeGenerator Resources.Designer.cs - + SettingsSingleFileGenerator Settings.Designer.cs @@ -215,7 +216,7 @@ PreserveNewest - + PreserveNewest