diff options
Diffstat (limited to 'src/conf_mode')
| -rwxr-xr-x | src/conf_mode/container.py | 7 | ||||
| -rwxr-xr-x | src/conf_mode/interfaces_vxlan.py | 2 | ||||
| -rwxr-xr-x | src/conf_mode/protocols_bgp.py | 11 | ||||
| -rwxr-xr-x | src/conf_mode/service_console-server.py | 8 | ||||
| -rwxr-xr-x | src/conf_mode/system_login.py | 21 | ||||
| -rwxr-xr-x | src/conf_mode/vpn_ipsec.py | 27 |
6 files changed, 72 insertions, 4 deletions
diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 3636b0871..18d660a4e 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -289,6 +289,13 @@ def verify(container): if 'registry' in container: for registry, registry_config in container['registry'].items(): + if 'mirror' in registry_config: + if 'host_name' in registry_config['mirror'] and 'address' in registry_config['mirror']: + raise ConfigError(f'Container registry mirror address/host-name are mutually exclusive!') + + if 'path' in registry_config['mirror'] and not registry_config['mirror']['path'].startswith('/'): + raise ConfigError('Container registry mirror path must start with "/"!') + if 'authentication' not in registry_config: continue if not {'username', 'password'} <= set(registry_config['authentication']): diff --git a/src/conf_mode/interfaces_vxlan.py b/src/conf_mode/interfaces_vxlan.py index 68646e8ff..256b65708 100755 --- a/src/conf_mode/interfaces_vxlan.py +++ b/src/conf_mode/interfaces_vxlan.py @@ -95,6 +95,8 @@ def verify(vxlan): if 'group' in vxlan: if 'source_interface' not in vxlan: raise ConfigError('Multicast VXLAN requires an underlaying interface') + if 'remote' in vxlan: + raise ConfigError('Both group and remote cannot be specified') verify_source_interface(vxlan) if not any(tmp in ['group', 'remote', 'source_address', 'source_interface'] for tmp in vxlan): diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py index c4af717af..53e83c3b4 100755 --- a/src/conf_mode/protocols_bgp.py +++ b/src/conf_mode/protocols_bgp.py @@ -523,12 +523,21 @@ def verify(config_dict): raise ConfigError( 'Please unconfigure import vrf commands before using vpn commands in dependent VRFs!') + if (dict_search('route_map.vrf.import', afi_config) is not None + or dict_search('import.vrf', afi_config) is not None): # FRR error: please unconfigure vpn to vrf commands before # using import vrf commands - if 'vpn' in afi_config['import'] or dict_search('export.vpn', afi_config) != None: + if ('vpn' in afi_config['import'] + or dict_search('export.vpn', afi_config) is not None): raise ConfigError('Please unconfigure VPN to VRF commands before '\ 'using "import vrf" commands!') + if (dict_search('route_map.vpn.import', afi_config) is not None + or dict_search('route_map.vpn.export', afi_config) is not None) : + raise ConfigError('Please unconfigure route-map VPN to VRF commands before '\ + 'using "import vrf" commands!') + + # Verify that the export/import route-maps do exist for export_import in ['export', 'import']: tmp = dict_search(f'route_map.vpn.{export_import}', afi_config) diff --git a/src/conf_mode/service_console-server.py b/src/conf_mode/service_console-server.py index b112add3f..b83c6dfb1 100755 --- a/src/conf_mode/service_console-server.py +++ b/src/conf_mode/service_console-server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2018-2021 VyOS maintainers and contributors +# Copyright (C) 2018-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 @@ -98,6 +98,12 @@ def generate(proxy): return None def apply(proxy): + if not os.path.exists('/etc/dropbear/dropbear_rsa_host_key'): + call('dropbearkey -t rsa -s 4096 -f /etc/dropbear/dropbear_rsa_host_key') + + if not os.path.exists('/etc/dropbear/dropbear_ecdsa_host_key'): + call('dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ecdsa_host_key') + call('systemctl daemon-reload') call('systemctl stop dropbear@*.service conserver-server.service') diff --git a/src/conf_mode/system_login.py b/src/conf_mode/system_login.py index d3a969d9b..1e6061ecf 100755 --- a/src/conf_mode/system_login.py +++ b/src/conf_mode/system_login.py @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os +import warnings from passlib.hosts import linux_context from psutil import users @@ -24,11 +25,17 @@ from pwd import getpwuid from sys import exit from time import sleep +from vyos.base import Warning from vyos.config import Config from vyos.configverify import verify_vrf from vyos.template import render from vyos.template import is_ipv4 -from vyos.utils.auth import get_current_user +from vyos.utils.auth import ( + DEFAULT_PASSWORD, + EPasswdStrength, + evaluate_strength, + get_current_user +) from vyos.utils.configfs import delete_cli_node from vyos.utils.configfs import add_cli_node from vyos.utils.dict import dict_search @@ -146,6 +153,18 @@ def verify(login): if s_user.pw_name == user and s_user.pw_uid < MIN_USER_UID: raise ConfigError(f'User "{user}" can not be created, conflict with local system account!') + # T6353: Check password for complexity using cracklib. + # A user password should be sufficiently complex + plaintext_password = dict_search( + path='authentication.plaintext_password', + dict_object=user_config + ) or None + + if plaintext_password is not None: + result = evaluate_strength(plaintext_password) + if result['strength'] == EPasswdStrength.WEAK: + Warning(result['error']) + for pubkey, pubkey_options in (dict_search('authentication.public_keys', user_config) or {}).items(): if 'type' not in pubkey_options: raise ConfigError(f'Missing type for public-key "{pubkey}"!') diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index 25604d2a2..71a503e61 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -156,6 +156,8 @@ def get_config(config=None): _, vti = get_interface_dict(conf, ['interfaces', 'vti'], vti_interface) ipsec['vti_interface_dicts'][vti_interface] = vti + ipsec['vpp_ipsec_exists'] = conf.exists(['vpp', 'settings', 'ipsec']) + return ipsec def get_dhcp_address(iface): @@ -484,6 +486,17 @@ def verify(ipsec): else: raise ConfigError(f"Missing ike-group on site-to-site peer {peer}") + # verify encryption algorithm compatibility for IKE with VPP + if ipsec['vpp_ipsec_exists']: + ike_group = ipsec['ike_group'][peer_conf['ike_group']] + for proposal, proposal_config in ike_group.get('proposal', {}).items(): + algs = ['gmac', 'serpent', 'twofish'] + if any(alg in proposal_config['encryption'] for alg in algs): + raise ConfigError( + f'Encryption algorithm {proposal_config["encryption"]} cannot be used ' + f'for IKE proposal {proposal} for site-to-site peer {peer} with VPP' + ) + if 'authentication' not in peer_conf or 'mode' not in peer_conf['authentication']: raise ConfigError(f"Missing authentication on site-to-site peer {peer}") @@ -562,7 +575,7 @@ def verify(ipsec): esp_group_name = tunnel_conf['esp_group'] if 'esp_group' in tunnel_conf else peer_conf['default_esp_group'] - if esp_group_name not in ipsec['esp_group']: + if esp_group_name not in ipsec.get('esp_group'): raise ConfigError(f"Invalid esp-group on tunnel {tunnel} for site-to-site peer {peer}") esp_group = ipsec['esp_group'][esp_group_name] @@ -574,6 +587,18 @@ def verify(ipsec): if ('local' in tunnel_conf and 'prefix' in tunnel_conf['local']) or ('remote' in tunnel_conf and 'prefix' in tunnel_conf['remote']): raise ConfigError(f"Local/remote prefix cannot be used with ESP transport mode on tunnel {tunnel} for site-to-site peer {peer}") + # verify ESP encryption algorithm compatibility with VPP + # because Marvel plugin for VPP doesn't support all algorithms that Strongswan does + if ipsec['vpp_ipsec_exists']: + for proposal, proposal_config in esp_group.get('proposal', {}).items(): + algs = ['aes128', 'aes192', 'aes256', 'aes128gcm128', 'aes192gcm128', 'aes256gcm128'] + if proposal_config['encryption'] not in algs: + raise ConfigError( + f'Encryption algorithm {proposal_config["encryption"]} cannot be used ' + f'for ESP proposal {proposal} on tunnel {tunnel} for site-to-site peer {peer} with VPP' + ) + + def cleanup_pki_files(): for path in [CERT_PATH, CA_PATH, CRL_PATH, KEY_PATH, PUBKEY_PATH]: if not os.path.exists(path): |
