diff --git a/plaso/parsers/text_plugins/iis.py b/plaso/parsers/text_plugins/iis.py index fe6e5957f1..94c2da1800 100644 --- a/plaso/parsers/text_plugins/iis.py +++ b/plaso/parsers/text_plugins/iis.py @@ -95,9 +95,17 @@ class WinIISTextPlugin(interface.TextPlugin): lambda tokens: int(tokens[0], 10) ) + # A scoped literal IPv6 address has a zone index suffix, such as "%3" or + # "%eth0", which pyparsing_common.ipv6_address does not support. + _ZONE_INDEX = pyparsing.Combine( + pyparsing.Literal("%") + pyparsing.Word(pyparsing.alphanums) + ) + _IP_ADDRESS = ( pyparsing.pyparsing_common.ipv4_address - | pyparsing.pyparsing_common.ipv6_address + | pyparsing.Combine( + pyparsing.pyparsing_common.ipv6_address + pyparsing.Opt(_ZONE_INDEX) + ) | _BLANK ) diff --git a/tests/parsers/text_plugins/iis.py b/tests/parsers/text_plugins/iis.py index 8140b11b93..60bfbef9d0 100644 --- a/tests/parsers/text_plugins/iis.py +++ b/tests/parsers/text_plugins/iis.py @@ -11,6 +11,26 @@ class WinIISTextPluginTest(test_lib.TextPluginTestCase): """Tests for the Windows IIS text parser plugin.""" + # pylint: disable=protected-access + + def testIPAddressWithZoneIndex(self): + """Tests the _IP_ADDRESS structure with a scoped IPv6 address.""" + plugin = iis.WinIISTextPlugin() + + structure = plugin._IP_ADDRESS.parse_string( + "fe80::1ff:fe23:4567:890a%3", parse_all=True + ) + self.assertEqual(structure[0], "fe80::1ff:fe23:4567:890a%3") + + structure = plugin._IP_ADDRESS.parse_string("fe80::1%eth0", parse_all=True) + self.assertEqual(structure[0], "fe80::1%eth0") + + structure = plugin._IP_ADDRESS.parse_string("::1", parse_all=True) + self.assertEqual(structure[0], "::1") + + structure = plugin._IP_ADDRESS.parse_string("10.10.10.100", parse_all=True) + self.assertEqual(structure[0], "10.10.10.100") + def testProcessWithIIS6Log(self): """Tests the Process function with an IIS 6 log file.""" plugin = iis.WinIISTextPlugin()