diff options
author | Andrew Topp <atopp@aus-it.com.au> | 2025-05-09 18:17:01 +1000 |
---|---|---|
committer | Andrew Topp <atopp@aus-it.com.au> | 2025-05-09 18:17:01 +1000 |
commit | 7c9f908f8658126bbe0e9da9dc71be3db45bf940 (patch) | |
tree | d032757dcafdd48f2920680e0234c447ede0b253 /src | |
parent | c8e468d4bf720f15e1c0232091399a45e8d9949b (diff) | |
download | vyos-1x-7c9f908f8658126bbe0e9da9dc71be3db45bf940.tar.gz vyos-1x-7c9f908f8658126bbe0e9da9dc71be3db45bf940.zip |
policy: T5069: large-community-list regex validator should allow whitespace
* Re-introduce the whitespace/pattern matches ' ' and '_' as allowed
* Perform a general Python regex validity check (not 100% 1003.2, but in combination
with allowedChars, pretty close)
* Introduce a warning against potentially malformed or over-complex patterns,
but leave it up to the user to resolve - there are plenty of useful
expressions we cannot validate easily
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/policy.py | 16 | ||||
-rwxr-xr-x | src/validators/bgp-large-community-list | 21 |
2 files changed, 31 insertions, 6 deletions
diff --git a/src/conf_mode/policy.py b/src/conf_mode/policy.py index a90e33e81..ec9005890 100755 --- a/src/conf_mode/policy.py +++ b/src/conf_mode/policy.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import re from sys import exit from vyos.config import Config @@ -24,9 +25,20 @@ from vyos.frrender import get_frrender_dict from vyos.utils.dict import dict_search from vyos.utils.process import is_systemd_service_running from vyos import ConfigError +from vyos.base import Warning from vyos import airbag airbag.enable() +# Sanity checks for large-community-list regex: +# * Require complete 3-tuples, no blank members. Catch missed & doubled colons. +# * Permit appropriate community separators (whitespace, underscore) +# * Permit common regex between tuples while requiring at least one separator +# (eg, "1:1:1_.*_4:4:4", matching "1:1:1 4:4:4" and "1:1:1 2:2:2 4:4:4", +# but not "1:1:13 24:4:4") +# Best practice: stick with basic patterns, mind your wildcards and whitespace. +# Regex that doesn't match this pattern will be allowed with a warning. +large_community_regex_pattern = r'([^: _]+):([^: _]+):([^: _]+)([ _]([^:]+):([^: _]+):([^: _]+))*' + def community_action_compatibility(actions: dict) -> bool: """ Check compatibility of values in community and large community sections @@ -147,6 +159,10 @@ def verify(config_dict): if 'regex' not in rule_config: raise ConfigError(f'A regex {mandatory_error}') + if policy_type == 'large_community_list': + if not re.fullmatch(large_community_regex_pattern, rule_config['regex']): + Warning(f'"policy large-community-list {instance} rule {rule} regex" does not follow expected form and may not match as expected.') + if policy_type in ['prefix_list', 'prefix_list6']: if 'prefix' not in rule_config: raise ConfigError(f'A prefix {mandatory_error}') diff --git a/src/validators/bgp-large-community-list b/src/validators/bgp-large-community-list index 9ba5b27eb..75276630c 100755 --- a/src/validators/bgp-large-community-list +++ b/src/validators/bgp-large-community-list @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2023 VyOS maintainers and contributors +# Copyright (C) 2021-2025 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as @@ -17,18 +17,27 @@ import re import sys -pattern = '(.*):(.*):(.*)' -allowedChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '+', '*', '?', '^', '$', '(', ')', '[', ']', '{', '}', '|', '\\', ':', '-' } +allowedChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '+', '*', '?', '^', '$', '(', ')', '[', ']', '{', '}', '|', '\\', ':', '-', '_', ' ' } if __name__ == '__main__': if len(sys.argv) != 2: sys.exit(1) - value = sys.argv[1].split(':') - if not len(value) == 3: + value = sys.argv[1] + + # Require at least one well-formed large-community tuple in the pattern. + tmp = value.split(':') + if len(tmp) < 3: + sys.exit(1) + + # Simple guard against invalid community & 1003.2 pattern chars + if not set(value).issubset(allowedChars): sys.exit(1) - if not (re.match(pattern, sys.argv[1]) and set(sys.argv[1]).issubset(allowedChars)): + # Don't feed FRR badly formed regex + try: + re.compile(value) + except re.error: sys.exit(1) sys.exit(0) |