diff options
Diffstat (limited to 'src/validators')
26 files changed, 370 insertions, 40 deletions
diff --git a/src/validators/as-number-list b/src/validators/as-number-list new file mode 100755 index 000000000..432d44180 --- /dev/null +++ b/src/validators/as-number-list @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (C) 2022 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if [ $# -lt 1 ]; then + echo "Illegal number of parameters" + exit 1 +fi + +for var in "$@"; do + ${vyos_validators_dir}/numeric --range 1-4294967294 $var + if [ $? -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/src/validators/bgp-route-target b/src/validators/bgp-rd-rt index e7e4d403f..b2b69c9be 100755 --- a/src/validators/bgp-route-target +++ b/src/validators/bgp-rd-rt @@ -19,29 +19,37 @@ from vyos.template import is_ipv4 parser = ArgumentParser() group = parser.add_mutually_exclusive_group() -group.add_argument('--single', action='store', help='Validate and allow only one route-target') -group.add_argument('--multi', action='store', help='Validate multiple, whitespace separated route-targets') +group.add_argument('--route-distinguisher', action='store', help='Validate BGP route distinguisher') +group.add_argument('--route-target', action='store', help='Validate one BGP route-target') +group.add_argument('--route-target-multi', action='store', help='Validate multiple, whitespace separated BGP route-targets') args = parser.parse_args() -def is_valid_rt(rt): - # every route target needs to have a colon and must consists of two parts +def is_valid(rt): + """ Verify BGP RD/RT - both can be verified using the same logic """ + # every RD/RT (route distinguisher/route target) needs to have a colon and + # must consists of two parts value = rt.split(':') if len(value) != 2: return False - # A route target must either be only numbers, or the first part must be an - # IPv4 address + + # An RD/RT must either be only numbers, or the first part must be an IPv4 + # address if (is_ipv4(value[0]) or value[0].isdigit()) and value[1].isdigit(): return True return False if __name__ == '__main__': - if args.single: - if not is_valid_rt(args.single): + if args.route_distinguisher: + if not is_valid(args.route_distinguisher): + exit(1) + + elif args.route_target: + if not is_valid(args.route_target): exit(1) - elif args.multi: - for rt in args.multi.split(' '): - if not is_valid_rt(rt): + elif args.route_target_multi: + for rt in args.route_target_multi.split(' '): + if not is_valid(rt): exit(1) else: diff --git a/src/validators/ip-address b/src/validators/ip-address index 51fb72c85..11d6df09e 100755 --- a/src/validators/ip-address +++ b/src/validators/ip-address @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-cidr b/src/validators/ip-cidr index 987bf84ca..60d2ac295 100755 --- a/src/validators/ip-cidr +++ b/src/validators/ip-cidr @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-cidr $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP CIDR" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-host b/src/validators/ip-host index f2906e8cf..77c578fa2 100755 --- a/src/validators/ip-host +++ b/src/validators/ip-host @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-host $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP host" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-prefix b/src/validators/ip-prefix index e58aad395..e5a64fea8 100755 --- a/src/validators/ip-prefix +++ b/src/validators/ip-prefix @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-any-net $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IP prefix" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ip-protocol b/src/validators/ip-protocol index 078f8e319..c4c882502 100755 --- a/src/validators/ip-protocol +++ b/src/validators/ip-protocol @@ -31,11 +31,12 @@ if __name__ == '__main__': pattern = "!?\\b(all|ip|hopopt|icmp|igmp|ggp|ipencap|st|tcp|egp|igp|pup|udp|" \ "tcp_udp|hmp|xns-idp|rdp|iso-tp4|dccp|xtp|ddp|idpr-cmtp|ipv6|" \ - "ipv6-route|ipv6-frag|idrp|rsvp|gre|esp|ah|skip|ipv6-icmp|" \ + "ipv6-route|ipv6-frag|idrp|rsvp|gre|esp|ah|skip|ipv6-icmp|icmpv6|" \ "ipv6-nonxt|ipv6-opts|rspf|vmtp|eigrp|ospf|ax.25|ipip|etherip|" \ "encap|99|pim|ipcomp|vrrp|l2tp|isis|sctp|fc|mobility-header|" \ "udplite|mpls-in-ip|manet|hip|shim6|wesp|rohc)\\b" if re.match(pattern, input): exit(0) + print(f'Error: {input} is not a valid IP protocol') exit(1) diff --git a/src/validators/ipv4 b/src/validators/ipv4 index 53face090..8676d5800 100755 --- a/src/validators/ipv4 +++ b/src/validators/ipv4 @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4 $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not IPv4" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-address b/src/validators/ipv4-address index 872a7645a..058db088b 100755 --- a/src/validators/ipv4-address +++ b/src/validators/ipv4-address @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-host b/src/validators/ipv4-host index f42feffa4..74b8c36a7 100755 --- a/src/validators/ipv4-host +++ b/src/validators/ipv4-host @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4-host $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 host" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-multicast b/src/validators/ipv4-multicast index e5cbc9532..3f28c51db 100755 --- a/src/validators/ipv4-multicast +++ b/src/validators/ipv4-multicast @@ -1,3 +1,10 @@ #!/bin/sh -ipaddrcheck --is-ipv4-multicast $1 +ipaddrcheck --is-ipv4-multicast $1 && ipaddrcheck --is-ipv4-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 multicast address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-prefix b/src/validators/ipv4-prefix index 8ec8a2c45..7e1e0e8dd 100755 --- a/src/validators/ipv4-prefix +++ b/src/validators/ipv4-prefix @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv4-net $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv4 prefix" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv4-range b/src/validators/ipv4-range index cc59039f1..6492bfc52 100755 --- a/src/validators/ipv4-range +++ b/src/validators/ipv4-range @@ -7,6 +7,11 @@ ip2dec () { printf '%d\n' "$((a * 256 ** 3 + b * 256 ** 2 + c * 256 + d))" } +error_exit() { + echo "Error: $1 is not a valid IPv4 address range" + exit 1 +} + # Only run this if there is a hypen present in $1 if [[ "$1" =~ "-" ]]; then # This only works with real bash (<<<) - split IP addresses into array with @@ -15,21 +20,21 @@ if [[ "$1" =~ "-" ]]; then ipaddrcheck --is-ipv4-single ${strarr[0]} if [ $? -gt 0 ]; then - exit 1 + error_exit $1 fi ipaddrcheck --is-ipv4-single ${strarr[1]} if [ $? -gt 0 ]; then - exit 1 + error_exit $1 fi start=$(ip2dec ${strarr[0]}) stop=$(ip2dec ${strarr[1]}) if [ $start -ge $stop ]; then - exit 1 + error_exit $1 fi exit 0 fi -exit 1 +error_exit $1 diff --git a/src/validators/ipv6 b/src/validators/ipv6 index f18d4a63e..4ae130eb5 100755 --- a/src/validators/ipv6 +++ b/src/validators/ipv6 @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6 $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not IPv6" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-address b/src/validators/ipv6-address index e5d68d756..1fca77668 100755 --- a/src/validators/ipv6-address +++ b/src/validators/ipv6-address @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-host b/src/validators/ipv6-host index f7a745077..7085809a9 100755 --- a/src/validators/ipv6-host +++ b/src/validators/ipv6-host @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6-host $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 host" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-link-local b/src/validators/ipv6-link-local new file mode 100755 index 000000000..05e693b77 --- /dev/null +++ b/src/validators/ipv6-link-local @@ -0,0 +1,12 @@ +#!/usr/bin/python3 + +import sys +from vyos.validate import is_ipv6_link_local + +if __name__ == '__main__': + if len(sys.argv)>1: + addr = sys.argv[1] + if not is_ipv6_link_local(addr): + sys.exit(1) + + sys.exit(0) diff --git a/src/validators/ipv6-multicast b/src/validators/ipv6-multicast index 66cd90c9c..5aa7d734a 100755 --- a/src/validators/ipv6-multicast +++ b/src/validators/ipv6-multicast @@ -1,3 +1,10 @@ #!/bin/sh -ipaddrcheck --is-ipv6-multicast $1 +ipaddrcheck --is-ipv6-multicast $1 && ipaddrcheck --is-ipv6-single $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 multicast address" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-prefix b/src/validators/ipv6-prefix index e43616350..890dda723 100755 --- a/src/validators/ipv6-prefix +++ b/src/validators/ipv6-prefix @@ -1,3 +1,10 @@ #!/bin/sh ipaddrcheck --is-ipv6-net $1 + +if [ $? -gt 0 ]; then + echo "Error: $1 is not a valid IPv6 prefix" + exit 1 +fi + +exit 0
\ No newline at end of file diff --git a/src/validators/ipv6-range b/src/validators/ipv6-range index 033b6461b..7080860c4 100755 --- a/src/validators/ipv6-range +++ b/src/validators/ipv6-range @@ -1,16 +1,20 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 -import sys -import re -from vyos.template import is_ipv6 +from ipaddress import IPv6Address +from sys import argv, exit if __name__ == '__main__': - if len(sys.argv)>1: - ipv6_range = sys.argv[1] - # Regex for ipv6-ipv6 https://regexr.com/ - if re.search('([a-f0-9:]+:+)+[a-f0-9]+-([a-f0-9:]+:+)+[a-f0-9]+', ipv6_range): - for tmp in ipv6_range.split('-'): - if not is_ipv6(tmp): - sys.exit(1) - - sys.exit(0) + if len(argv) > 1: + # try to pass validation and raise an error if failed + try: + ipv6_range = argv[1] + range_left = ipv6_range.split('-')[0] + range_right = ipv6_range.split('-')[1] + if not IPv6Address(range_left) < IPv6Address(range_right): + raise ValueError(f'left element {range_left} must be less than right element {range_right}') + except Exception as err: + print(f'Error: {ipv6_range} is not a valid IPv6 range: {err}') + exit(1) + else: + print('Error: an IPv6 range argument must be provided') + exit(1) diff --git a/src/validators/mac-address-firewall b/src/validators/mac-address-firewall new file mode 100755 index 000000000..70551f86d --- /dev/null +++ b/src/validators/mac-address-firewall @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018-2022 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import re +import sys + +pattern = "^!?([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" + +if __name__ == '__main__': + if len(sys.argv) != 2: + sys.exit(1) + if not re.match(pattern, sys.argv[1]): + sys.exit(1) + sys.exit(0) diff --git a/src/validators/port-multi b/src/validators/port-multi new file mode 100755 index 000000000..bd6f0ef60 --- /dev/null +++ b/src/validators/port-multi @@ -0,0 +1,52 @@ +#!/usr/bin/python3 + +from sys import argv +from sys import exit +import re + +from vyos.util import read_file + +services_file = '/etc/services' + +def get_services(): + names = [] + service_data = read_file(services_file, "") + for line in service_data.split("\n"): + if not line or line[0] == '#': + continue + tmp = line.split() + names.append(tmp[0]) + if len(tmp) > 2: + # Add port aliases to service list, too + names.extend(tmp[2:]) + # remove duplicate entries (e.g. echo) from list + names = list(dict.fromkeys(names)) + return names + +if __name__ == '__main__': + if len(argv)>1: + ports = argv[1].split(",") + services = get_services() + + for port in ports: + if port and port[0] == '!': + port = port[1:] + if re.match('^[0-9]{1,5}-[0-9]{1,5}$', port): + port_1, port_2 = port.split('-') + if int(port_1) not in range(1, 65536) or int(port_2) not in range(1, 65536): + print(f'Error: {port} is not a valid port range') + exit(1) + if int(port_1) > int(port_2): + print(f'Error: {port} is not a valid port range') + exit(1) + elif port.isnumeric(): + if int(port) not in range(1, 65536): + print(f'Error: {port} is not a valid port') + exit(1) + elif port not in services: + print(f'Error: {port} is not a valid service name') + exit(1) + else: + exit(2) + + exit(0) diff --git a/src/validators/port-range b/src/validators/port-range index abf0b09d5..5468000a7 100755 --- a/src/validators/port-range +++ b/src/validators/port-range @@ -3,16 +3,37 @@ import sys import re +from vyos.util import read_file + +services_file = '/etc/services' + +def get_services(): + names = [] + service_data = read_file(services_file, "") + for line in service_data.split("\n"): + if not line or line[0] == '#': + continue + names.append(line.split(None, 1)[0]) + return names + +def error(port_range): + print(f'Error: {port_range} is not a valid port or port range') + sys.exit(1) + if __name__ == '__main__': if len(sys.argv)>1: port_range = sys.argv[1] - if re.search('[0-9]{1,5}-[0-9]{1,5}', port_range): - for tmp in port_range.split('-'): - if int(tmp) not in range(1, 65535): - sys.exit(1) - else: - if int(port_range) not in range(1, 65535): - sys.exit(1) + if re.match('^[0-9]{1,5}-[0-9]{1,5}$', port_range): + port_1, port_2 = port_range.split('-') + if int(port_1) not in range(1, 65536) or int(port_2) not in range(1, 65536): + error(port_range) + if int(port_1) > int(port_2): + error(port_range) + elif port_range.isnumeric() and int(port_range) not in range(1, 65536): + error(port_range) + elif not port_range.isnumeric() and port_range not in get_services(): + print(f'Error: {port_range} is not a valid service name') + sys.exit(1) else: sys.exit(2) diff --git a/src/validators/range b/src/validators/range new file mode 100755 index 000000000..d4c25f3c4 --- /dev/null +++ b/src/validators/range @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 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 +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import re +import sys +import argparse + +class MalformedRange(Exception): + pass + +def validate_range(value, min=None, max=None): + try: + lower, upper = re.match(r'^(\d+)-(\d+)$', value).groups() + + lower, upper = int(lower), int(upper) + + if int(lower) > int(upper): + raise MalformedRange("the lower bound exceeds the upper bound".format(value)) + + if min is not None: + if lower < min: + raise MalformedRange("the lower bound must not be less than {}".format(min)) + + if max is not None: + if upper > max: + raise MalformedRange("the upper bound must not be greater than {}".format(max)) + + except (AttributeError, ValueError): + raise MalformedRange("range syntax error") + +parser = argparse.ArgumentParser(description='Range validator.') +parser.add_argument('--min', type=int, action='store') +parser.add_argument('--max', type=int, action='store') +parser.add_argument('value', action='store') + +if __name__ == '__main__': + args = parser.parse_args() + + try: + validate_range(args.value, min=args.min, max=args.max) + except MalformedRange as e: + print("Incorrect range '{}': {}".format(args.value, e)) + sys.exit(1) diff --git a/src/validators/script b/src/validators/script index 1d8a27e5c..4ffdeb2a0 100755 --- a/src/validators/script +++ b/src/validators/script @@ -36,7 +36,7 @@ if __name__ == '__main__': # File outside the config dir is just a warning if not vyos.util.file_is_persistent(script): - sys.exit( - f'Warning: file {path} is outside the / config directory\n' + sys.exit(0)( + f'Warning: file {script} is outside the "/config" directory\n' 'It will not be automatically migrated to a new image on system update' ) diff --git a/src/validators/tcp-flag b/src/validators/tcp-flag new file mode 100755 index 000000000..1496b904a --- /dev/null +++ b/src/validators/tcp-flag @@ -0,0 +1,17 @@ +#!/usr/bin/python3 + +import sys +import re + +if __name__ == '__main__': + if len(sys.argv)>1: + flag = sys.argv[1] + if flag and flag[0] == '!': + flag = flag[1:] + if flag not in ['syn', 'ack', 'rst', 'fin', 'urg', 'psh', 'ecn', 'cwr']: + print(f'Error: {flag} is not a valid TCP flag') + sys.exit(1) + else: + sys.exit(2) + + sys.exit(0) |